Introduction
Redis distinguishes between two kinds of errors inside a transaction: syntax errors detected at queue time, and runtime errors that occur during EXEC. Understanding this distinction is critical — the behavior is different from most databases and can surprise developers.
Key Concepts
- Syntax error — an unknown or malformed command that Redis rejects immediately when queued; causes the entire transaction to be aborted on EXEC
- Runtime error — a command that is syntactically valid but fails during execution (e.g., INCR on a string); only that command fails; others execute
- No rollback — Redis has no ROLLBACK command; commands that already executed are permanent
- EXECABORT — the error returned by EXEC when a syntax error was queued
Real World Context
A payment service queues five commands in a transaction. One command uses the wrong type on a key. With SQL, the whole transaction would roll back. With Redis, four commands succeed and only the erroneous one fails — your application code must handle partial success.
Deep Dive
Here is what happens with a syntax error (typo in command name):
bashMULTI SET counter 1 INKR counter # (error) ERR unknown command 'INKR' # Redis marks transaction as errored EXEC # (error) EXECABORT Transaction discarded because of previous errors.
Notice that SET counter 1 also did NOT execute — the whole queue was discarded.
Now compare with a runtime error (wrong type):
bashSET mystring "hello" MULTI SET other "world" INCR mystring SET third "done" EXEC # 1) OK <- SET other succeeded # 2) (error) WRONGTYPE ... # 3) OK <- SET third succeeded
The INCR failed because mystring holds a string, not an integer. But both SET commands executed successfully. There is no rollback.
Common Pitfalls
- Assuming a runtime error aborts the transaction. It does not. Commands before and after the failing command still execute. Validate types before entering MULTI.
- Confusing syntax errors with runtime errors. A typo in a command name aborts everything; a wrong-type error only fails that one command.
- Not checking EXEC response elements. Each element in the EXEC response array can be either a result or an error. Always iterate and check for error objects in your client code.
Best Practices
- Verify key types with TYPE command before entering a transaction if your logic depends on them.
- In application code, check every entry in the EXEC response array for errors, not just the array itself.
- Use Lua scripting instead of MULTI/EXEC when you need true abort-on-error semantics — a Lua script stops executing on redis.call() errors.
Summary
- Syntax errors (unknown commands) abort the entire transaction on EXEC
- Runtime errors (wrong type, etc.) only fail that single command
- The remaining commands in the queue still execute after a runtime error
- Redis has no ROLLBACK — partial execution is possible
- Always check each element of the EXEC response for errors in client code
Code Examples
# Syntax error example — whole transaction aborted
MULTI
SET counter 1
INKR counter
# (error) ERR unknown command 'INKR'
EXEC
# (error) EXECABORT Transaction discarded because of previous errors.# Runtime error example — other commands still execute
SET mystring "hello"
MULTI
SET other "world"
INCR mystring
SET third "done"
EXEC
# 1) OK
# 2) (error) WRONGTYPE Operation against a key holding the wrong kind of value
# 3) OK