When running a LUA script via eval we may get an Redis error response (a RESP error line starting with -) for different reasons: 1) We executed a Redis command with redis.call() which returned an error. 2) We returned a result of a call redis.pcall() which itself returned an error. 3) We failed to execute a command via redis.call() because of some state (for example write command with EVAL_RO during OOM condition). 4) We returned a result of failed attempt to execute a command via redis.pcall() because of some state (for example write command with EVAL_RO during OOM condition).

Each of these returns the error differently and in cases 3,4 above the format seems a bit arbitrary based on what type of error state was encountered.

Details:

 1: config set maxmemory 1
 2: +OK
 3: eval "return redis.call('set','x','y')" 0
 4: -ERR Error running script (call to 71e6319f97b0fe8bdfa1c5df3ce4489946dda479): @user_script:1: @user_script: 1: -OOM command not allowed when used memory > 'maxmemory'.
 5: eval "return redis.pcall('set','x','y')" 0
 6: -@user_script: 1: -OOM command not allowed when used memory > 'maxmemory'.
 7: eval "return redis.call('select',99)" 0
 8: -ERR Error running script (call to 4ad5abfc50bbccb484223905f9a16f09cd043ba8): @user_script:1: ERR DB index is out of range
 9: eval "return redis.pcall('select',99)" 0
10: -ERR DB index is out of range
11: eval_ro "return redis.call('set','x','y')" 0
12: -ERR Error running script (call to 71e6319f97b0fe8bdfa1c5df3ce4489946dda479): @user_script:1: @user_script: 1: Write commands are not allowed from read-only scripts.
13: eval_ro "return redis.pcall('set','x','y')" 0
14: -@user_script: 1: Write commands are not allowed from read-only scripts.

Issues: - In line 4 (and 12) redis.call() failed because of pre-existing state (OOM/ro). Script execution is aborted with generic error (-ERR Error runnning script) wrapping the internal error (-OOM...). The wrapper includes a "stack trace" (@user_script:1). The internal error is also wrapped in a stack trace (this time with a space before the line number @user_script: 1). We should avoid the double stack trace.

  • In line 4 the internal error is formatted like a valid Redis error response (-OOM), but in line 12 we have a similar call that fails before of attempting to call a WRITE command from eval_ro. This time the internal error is just a string with error code or status marker (Write commands are not...). This is inconsistent.

  • In line 6 we return the error object we received from a failed redis.pcall() because of an OOM state. This isn't prefixed with any error code, which seems very unorthodox and should be fixed.

  • In line 8 we abort the script with an error because of an error in the command executed by a redis.call() (select 99). The error is wrapped generically with a "stack trace" and seems fine but this time the wrapped error's leading - was trimmed becoming inconsistent with line 4.

In addition to this here: https://github.com/redis/redis/blob/857dc5bacd85a9a4c31b7ef9eb350690ca0a85ad/src/script_lua.c#L447-L454 There's code (which in practice never executes) which returns the error string unwrapped by the "stack trace" if it fails to get it. In such a case we might return a double "-" sign or prepend the "-" sign to some random text like -Write commands are not allowed....