Redis error BUSY
BUSY Redis is busy running a script. You can only call SCRIPT KILL or SHUTDOWN NOSAVE.
A Lua script or function has held the server for longer than busy-reply-threshold (5 seconds by default), so Redis answers almost everything else with BUSY. Stop it with SCRIPT KILL (FUNCTION KILL for a function); if it has already written, only SHUTDOWN NOSAVE stops it.
BUSY Redis is busy running a script. You can only call SCRIPT KILL or SHUTDOWN NOSAVE.
Tested on Redis 8.10.2 and Valkey 8.1.10 (temporary servers) · Updated 9 October 2026
What it means
A Lua script (EVAL, EVALSHA) or a function (FCALL) runs atomically: while it runs, Redis does
nothing else. Other clients’ commands wait. Once the script has run for longer than
busy-reply-threshold (5,000 ms by default; its old name, lua-time-limit, still works), Redis
starts answering them, but only to say it’s busy:
BUSY Redis is busy running a script. You can only call SCRIPT KILL or SHUTDOWN NOSAVE.
For a function the wording names FUNCTION KILL instead, and a long module command gives
BUSY Redis is busy running a module command. The script itself keeps running. Nothing you send
runs until it ends or is stopped; even PING, GET and INFO got BUSY in the test below.
Stopping it depends on what it has done:
- It hasn’t written anything yet:
SCRIPT KILL(orFUNCTION KILL) stops it. The client that ran it gets an error and nothing changes, because the script made no changes. - It has already written: stopping it halfway would break the promise that a script runs
completely or not at all, so Redis refuses with
UNKILLABLE. Your choices are to wait for it to finish or to stop the whole server withSHUTDOWN NOSAVE, which doesn’t save, so the script’s half-done work isn’t persisted. Anything written since your last save or AOF write is lost too.
Common causes
- A loop that doesn’t end: a bug in a
whilecondition, or a retry loop inside the script. - A script that does too much at once: walking a big set or hash, deleting thousands of keys,
or calling
KEYSinside the script on a large database. - Data that grew. A script that took 50 ms on a small key takes seconds once the key holds millions of elements.
- A function (
FCALL) with any of the above.
A slow ordinary command, such as KEYS * on a big database, also holds up the server, but clients
wait for it rather than getting BUSY.
How to fix it
Stop the script
From another connection (yours is waiting on the script, or is another client):
redis-cli SCRIPT KILL # for EVAL / EVALSHA
redis-cli FUNCTION KILL # for FCALL
The BUSY message tells you which one: it names SCRIPT KILL for a script and FUNCTION KILL for
a function. SCRIPT KILL while a function is running gets the same BUSY reply; when nothing is
running you get NOTBUSY No scripts in execution right now.
If you get UNKILLABLE
UNKILLABLE Sorry the script already executed write commands against the dataset. You can either wait the script termination or kill the server in a hard way using the SHUTDOWN NOSAVE command.
If the script will finish, waiting is the safe choice. If it never will, SHUTDOWN NOSAVE and start
the server again: it comes back with what was last saved. On a replicated setup, check which server
becomes primary afterwards.
Find the script
The server log names it:
# Slow script detected: still in execution after 5000 milliseconds. You can try killing the script using the SCRIPT KILL command. Script name is: 694a5fe1ddb97a4c6a1bf299d9537c7d3d0f84e7.
For EVALSHA, that’s the SHA1 your application sends; search your code for the script, or compare
with the SHA1 that SCRIPT LOAD returns for each candidate.
Make scripts short, and killable for longer
- Do bounded work per call: process a batch of, say, 1,000 elements and return a cursor, and let the
application call again. Iterate with
SCAN/HSCAN/SSCANfrom the application, notKEYSin the script. - Do the reading and computing first and the writes last. Until its first write, a script can be killed.
- Mark scripts that only read with
#!lua flags=no-writes(or useEVAL_RO), so they can always be killed.
Don’t raise the threshold to hide it
A higher busy-reply-threshold doesn’t make the script faster: clients wait longer before being told
the server is busy. 0 turns the BUSY replies off altogether, so clients wait for as long as the
script runs. On AWS ElastiCache lua-time-limit is fixed at 5,000 ms, and when a script exceeds it
ElastiCache sends SCRIPT KILL and, if that fails, restarts the node, AWS’s docs say.
Reproduce it
Only on a temporary Redis 8.10.2 container, because a looping script blocks the whole server:
docker run --rm -d --name seo-redis-busy redis:8 redis-server
redis-cli CONFIG GET busy-reply-threshold # "5000"
redis-cli EVAL "while true do end" 0 # in one terminal
redis-cli PING # in another, 2 seconds later
The PING waited about 3 seconds, until the script had run for 5, then got:
(error) BUSY Redis is busy running a script. You can only call SCRIPT KILL or SHUTDOWN NOSAVE.
GET greeting and INFO server got the same. SCRIPT KILL returned OK, and the EVAL that had
been running returned:
(error) ERR Script killed by user with SCRIPT KILL... script: 694a5fe1ddb97a4c6a1bf299d9537c7d3d0f84e7, on @user_script:1.
A function that loops, loaded with FUNCTION LOAD and run with FCALL spin 0:
(error) BUSY Redis is busy running a script. You can only call FUNCTION KILL or SHUTDOWN NOSAVE.
SCRIPT KILL got that same reply; FUNCTION KILL returned OK.
A script that writes first, then loops (redis.call("SET","seo:busy","1") while true do end):
PING got BUSY as before, and SCRIPT KILL got:
(error) UNKILLABLE Sorry the script already executed write commands against the dataset. You can either wait the script termination or kill the server in a hard way using the SHUTDOWN NOSAVE command.
SHUTDOWN NOSAVE stopped the server (and with it the temporary container).
Valkey 8.1.10 names itself in the message:
BUSY Valkey is busy running a script. You can only call SCRIPT KILL or SHUTDOWN NOSAVE. Its
UNKILLABLE text was the same as Redis’s.
In Inlet
In a query tab, Stop also kills a long script that the tab is running. The server’s rule still
applies: a script that has already written can’t be killed by anyone. When another client’s script
holds the server, Inlet shows the BUSY message and links it to this page.
Related
Sources
- redis.io/docs/latest/develop/programmability/eval-intro/
- redis.io/docs/latest/commands/script-kill/
- redis.io/docs/latest/commands/function-kill/
- redis.io/docs/latest/commands/shutdown/
- github.com/redis/redis/blob/8.10.2/redis.conf
- github.com/redis/redis/blob/8.10.2/src/server.c
- github.com/valkey-io/valkey/blob/8.1.10/src/server.c
- docs.aws.amazon.com/AmazonElastiCache/latest/dg/ParameterGroups.Engine.html