What it means
Many Redis commands take fixed arguments followed by optional words: SET key value [NX | XX] [GET] [EX seconds | PX milliseconds | …], SCAN cursor [MATCH pattern] [COUNT count]. When Redis
meets an extra word it doesn’t expect, an option that’s missing its value, or two options that
exclude each other, it gives up with:
(error) ERR syntax error
Nothing ran. The message doesn’t say which word was wrong, so you have to compare what you sent with the command’s syntax.
A few commands say more: ZADD with both NX and XX replies
ERR XX and NX options at the same time are not compatible, and EXPIRE with NX and XX
replies ERR NX and XX, GT or LT options at the same time are not compatible.
If the count of arguments is wrong rather than their words, you get wrong number of arguments instead, and an unknown first word is an unknown command.
Common causes
- A value with spaces, not quoted.
SET greeting hello worldsends four arguments, andSETreadsworldas an option it doesn’t know. It’s an easy mistake in redis-cli and shell scripts. - Options that can’t be combined:
EXwithPX(orEXAT,PXAT,KEEPTTL),NXwithXX. - An option without its value:
SET k v EX,SCAN 0 MATCH. - A misspelt or invented option:
WITHSCOREforWITHSCORES,EXPIREinstead ofEX. - An option newer than the server. An option a server doesn’t know is an unknown word to it.
For example,
SETgainedKEEPTTLin Redis 6.0,GET,EXATandPXATin 6.2, andIFEQ,IFNE,IFDEQandIFDNEin 8.4;EXPIREgainedNX,XX,GTandLTin 7.0. Valkey has its own set: Valkey 8.1 takesSET … IFEQbut notIFDEQ.
How to fix it
Quote values that contain spaces
redis-cli SET greeting "hello world"
redis-cli SET greeting "$MESSAGE"
In a client library, pass the value as one argument; the library sends it as one piece whatever it contains.
Compare with the command’s syntax
COMMAND DOCS <command> lists every argument and option, in order, with the version each option
appeared in (since and history). The command’s page on redis.io shows the same. Check:
- each option appears once, and only one of each exclusive group (
NX | XX,EX | PX | EXAT | PXAT | KEEPTTL); - every option that takes a value has one (
EX 60,MATCH user:*,COUNT 100); - the fixed arguments come first, in their order.
Check the server’s version
redis-cli INFO server | grep -E '^(redis_version|valkey_version):'
If the option is newer than the server, upgrade it or do the same thing with more than one
command: for SET … GET, a GET and a SET inside MULTI … EXEC.
Reproduce it
Redis 8.10.2 and Valkey 8.1.10 replied identically, in database 15:
SET seo:err:greeting hello world
(error) ERR syntax error
SET seo:err:greeting 'hello world'
OK
SET seo:err:greeting hi EX 10 PX 100
(error) ERR syntax error
SET seo:err:greeting hi NX XX
(error) ERR syntax error
SET seo:err:greeting hi KEEPTTL EX 10
(error) ERR syntax error
SET seo:err:greeting hi EXPIRE 10
(error) ERR syntax error
SET seo:err:greeting hi EX
(error) ERR syntax error
SCAN 0 MATCH
(error) ERR syntax error
ZRANGE seo:err:z 0 -1 WITHSCORE
(error) ERR syntax error
ZADD seo:err:z NX XX 1 a
(error) ERR XX and NX options at the same time are not compatible
ZADD seo:err:z GT LT 1 a
(error) ERR GT, LT, and/or NX options at the same time are not compatible
EXPIRE seo:err:greeting 10 NX XX
(error) ERR NX and XX, GT or LT options at the same time are not compatible
SCAN 0 COUNT 10 FOO, GETEX with both EX and PERSIST, and SORT with BY and nothing
after it each got ERR syntax error too.
An option one server has and the other doesn’t, SET seo:err:k v IFDEQ abc (Redis 8.4’s compare
by digest): Redis 8.10.2 replied (nil) (the key didn’t exist, so nothing was set), and Valkey
8.1.10 replied (error) ERR syntax error.
From a shell, on Redis, SET with an unquoted variable holding Ada Lovelace got
ERR syntax error, and quoting the variable fixed it.
In Inlet
Query tabs take redis-cli commands, one a line, and read quotes the way redis-cli does, so
SET greeting "hello world" sends one value. When the server refuses a command, Inlet shows its
message and links to this page.