Redis Error Guide: 'NOSCRIPT No matching script. Please use EVAL' — Reload the Script Cache
Fix NOSCRIPT No matching script Please use EVAL in Redis: understand EVALSHA script cache misses after restart, SCRIPT FLUSH, failover, and the EVALSHA-then-EVAL fallback.
- #redis
- #troubleshooting
- #errors
- #scripting
Overview
NOSCRIPT No matching script is returned by EVALSHA when the SHA1 you supplied is not in the server’s script cache. Redis lets you run a Lua script by its SHA1 (via EVALSHA) instead of sending the whole body every time, but that cache is in-memory and not persisted. Anything that clears it — a restart, SCRIPT FLUSH, a failover to a node that never saw the script — makes EVALSHA miss.
The literal error clients receive:
(error) NOSCRIPT No matching script. Please use EVAL.
The message tells you the remedy: fall back to EVAL (which sends the body and re-caches it), or reload the script with SCRIPT LOAD. The real question is why the cache lost your script — and whether your client implements the standard EVALSHA → NOSCRIPT → EVAL fallback that makes this self-healing.
Symptoms
EVALSHAfails withNOSCRIPTwhileEVALof the same script works.- Started right after a Redis restart,
SCRIPT FLUSH, or a failover. - Affects only clients that cache the SHA and never re-load it.
redis-cli EVALSHA e0e1f9ca3a2b... 1 mykey
(error) NOSCRIPT No matching script. Please use EVAL.
redis-cli SCRIPT EXISTS e0e1f9ca3a2b...
1) (integer) 0
Common Root Causes
1. Server restarted (script cache is not persisted)
The script cache lives only in memory; a restart empties it, so every cached SHA misses until reloaded.
redis-cli SCRIPT EXISTS <sha1>
redis-cli INFO server | grep -E 'uptime_in_seconds|run_id'
1) (integer) 0
uptime_in_seconds:73
A tiny uptime plus SCRIPT EXISTS 0 points straight at a recent restart.
2. SCRIPT FLUSH was called
An explicit SCRIPT FLUSH (sometimes as part of maintenance or FLUSHALL scripts) cleared the cache.
sudo journalctl -u redis-server --no-pager | grep -iE 'SCRIPT FLUSH|flush' | tail
3. Failover / new node never loaded the script
After a Sentinel/Cluster failover, the new master’s cache never had the SHA (scripts are not replicated to a node’s cache the way keys are).
redis-cli INFO replication | grep -E 'role|run_id'
redis-cli SCRIPT EXISTS <sha1>
4. Client caches the SHA but has no EVAL fallback
The client stored the SHA once and always uses EVALSHA, without the standard fallback to EVAL on NOSCRIPT.
# The robust pattern: EVALSHA, and on NOSCRIPT, EVAL (which re-caches)
redis-cli SCRIPT LOAD "return redis.call('GET', KEYS[1])"
Diagnostic Workflow
Step 1: Confirm the SHA is not cached
redis-cli SCRIPT EXISTS <sha1>
0 confirms NOSCRIPT is correct — the script is genuinely not in cache.
Step 2: Check server uptime and run_id for a restart/failover
redis-cli INFO server | grep -E 'uptime_in_seconds|run_id'
redis-cli INFO replication | grep -E 'role|master_replid'
Low uptime or a changed run_id/master explains the empty cache.
Step 3: Reload the script and re-check
redis-cli SCRIPT LOAD "$(cat myscript.lua)"
redis-cli SCRIPT EXISTS <sha1>
"e0e1f9ca3a2b..."
1) (integer) 1
Step 4: Verify EVAL works (fallback path)
redis-cli EVAL "$(cat myscript.lua)" 1 mykey
If EVAL works, the client just needs to run it on NOSCRIPT.
Step 5: Check the log for flush/restart events
sudo journalctl -u redis-server --no-pager | grep -iE 'Ready to accept|SCRIPT FLUSH|Saving' | tail
Example Root Cause Analysis
At 06:30, right after a planned Redis upgrade and restart, the rate-limiter service starts failing every request with NOSCRIPT No matching script. Please use EVAL. It uses a Lua script for atomic token-bucket logic and calls it exclusively by SHA1.
SCRIPT EXISTS on the SHA returns 0, and the server uptime is under two minutes — the restart wiped the in-memory script cache:
redis-cli SCRIPT EXISTS 8f5a... # -> 0
redis-cli INFO server | grep uptime_in_seconds # -> 95
The root cause is a client that caches the SHA at startup and never handles NOSCRIPT. The immediate recovery is to reload the script; the durable fix is the standard fallback:
# Immediate: re-load so EVALSHA hits again
redis-cli SCRIPT LOAD "$(cat token_bucket.lua)"
redis-cli SCRIPT EXISTS 8f5a... # -> 1
# Durable client pattern (pseudocode)
try:
EVALSHA sha, keys, args
except NOSCRIPT:
EVAL body, keys, args # runs AND re-caches; retry EVALSHA next time
With the fallback in place, a future restart or failover self-heals on the first call. Most mature Redis client libraries implement this automatically when you use their “register script” helper rather than calling EVALSHA directly.
Prevention Best Practices
- Always implement the
EVALSHA→ catchNOSCRIPT→EVALfallback; it makes restarts and failovers self-healing. Prefer your client library’s script-registration helper, which does this for you. - Treat the script cache as ephemeral — never assume a SHA persists across restarts or exists on a newly promoted node.
- Reload critical scripts on startup with
SCRIPT LOADas part of app bootstrap. - After a failover, expect the new master’s cache to be empty; the fallback covers it.
- Keep Lua scripts small and in version control; the SHA is derived from the exact body, so any whitespace change is a new SHA.
- Consider Redis Functions (
FUNCTION LOAD) for logic that should persist and replicate, where appropriate. - Paste the client error into the free incident assistant, and see more Redis guides.
Quick Command Reference
# Is the SHA cached?
redis-cli SCRIPT EXISTS <sha1>
# Restart / failover check
redis-cli INFO server | grep -E 'uptime_in_seconds|run_id'
redis-cli INFO replication | grep -E 'role|master_replid'
# Reload the script
redis-cli SCRIPT LOAD "$(cat myscript.lua)"
# Fallback path
redis-cli EVAL "$(cat myscript.lua)" 1 mykey
# Log events
sudo journalctl -u redis-server | grep -iE 'Ready to accept|SCRIPT FLUSH' | tail
Conclusion
NOSCRIPT No matching script. Please use EVAL means the SHA1 you sent to EVALSHA is not in the server’s (non-persisted, in-memory) script cache. The typical root causes are:
- The server restarted and cleared the cache.
SCRIPT FLUSHwas called.- A failover put you on a node that never loaded the script.
- A client that caches the SHA without an
EVALfallback.
The fix the error itself suggests — fall back to EVAL on NOSCRIPT — is also the permanent one. Implement the standard EVALSHA/EVAL fallback (or use your client’s script helper) and treat the cache as ephemeral, so a restart or failover heals itself on the next call.
Download the Free 500-Prompt DevOps AI Toolkit
500 battle-tested, copy-paste AI prompts engineered by a senior systems engineer — every one with fill-in placeholders and safety/back-out notes. Drop your email and it's yours.
- 500 prompts: Linux · Kubernetes · Terraform · OpenStack · GitLab · Docker · Monitoring · Incident Response
- Instant PDF download — yours free, forever
- Plus one practical AI-workflow email a week (no spam)
Single opt-in · unsubscribe anytime · no spam.