Redis is refusing to execute Lua scripts because it can’t find a matching script ID in its cache.
Here are the common reasons and how to fix them:
1. Script Never Loaded
Diagnosis: The script was never sent to Redis, or it was sent but Redis crashed before it could be cached.
Fix: Load the script using EVAL or EVALSHA with the script content. If using EVALSHA, you’ll need to know the SHA1 hash of your script. You can compute this locally with redis-cli --sha1.
# Example of loading a script directly (if you don't have the SHA)
redis-cli EVAL "local val = redis.call('GET', KEYS[1]); redis.call('SET', KEYS[1], ARGV[1]); return val" 1 mykey myval
# Example of loading a script by its SHA (if you know it)
redis-cli EVALSHA <sha1_hash_of_your_script> 0
Why it works: EVAL forces Redis to parse and execute the script, and it automatically caches the script and its SHA1 hash for future EVALSHA calls. EVALSHA requires the script to be already cached.
2. Script Evicted from Cache
Diagnosis: Redis has a limited cache for Lua scripts. If you load many scripts or your server is under memory pressure, older scripts might be evicted to make room for newer ones.
Fix: Reload the script. The most robust way is to always use EVALSHA and, if it fails with NOSCRIPT, fall back to EVAL to reload it.
# Example in Python using redis-py
import redis
r = redis.Redis(decode_responses=True)
script_sha = "your_script_sha1_hash"
script_content = "local val = redis.call('GET', KEYS[1]); redis.call('SET', KEYS[1], ARGV[1]); return val"
try:
result = r.evalsha(script_sha, 1, "mykey", "myval")
except redis.exceptions.NoScriptError:
print("Script not found, loading and executing...")
result = r.eval(script_content, 1, "mykey", "myval")
# Optionally, store the new SHA if you want to use it later
script_sha = r.script_load(script_content)
Why it works: The try...except block handles the NOSCRIPT error gracefully. When it occurs, it falls back to EVAL, which re-executes the script and, crucially, re-caches it with its SHA1 hash.
3. Client and Server SHA Mismatch
Diagnosis: The client library calculated the SHA1 hash of the script and sent EVALSHA with that hash. However, the script content on the server is subtly different from what the client thinks it is. This can happen if the script was modified on the server (e.g., via redis-cli or another client) but the client’s cached SHA is still for the old version.
Fix: Ensure consistency. Either clear the script cache on the server (not recommended in production unless you know what you’re doing) or, more practically, have your application client re-evaluate the script content to get the correct SHA and then use that. The try...except pattern from fix #2 handles this automatically.
Why it works: By using EVAL when EVALSHA fails, you’re effectively telling Redis "here’s the script content, use this." Redis will parse it, execute it, and cache the new correct SHA.
4. Corrupted Script Cache
Diagnosis: In rare cases, the script cache in Redis might become corrupted.
Fix: Restart the Redis server. This will clear the script cache (among other things).
# On systems with systemd
sudo systemctl restart redis-server
# On systems with init.d
sudo service redis-server restart
Why it works: A server restart re-initializes Redis, including clearing its in-memory script cache. All scripts will need to be reloaded by clients.
5. Network Partitions or Redis Cluster Issues
Diagnosis: In a Redis Cluster setup, if a script is loaded on one shard but the client attempts to execute it via EVALSHA on a different shard that hasn’t seen the script, NOSCRIPT will occur. This can also happen if a Redis instance is temporarily unavailable and the client retries with an old SHA.
Fix: Ensure your client logic properly handles script loading across all relevant shards or use a client library that manages this transparently. For cluster issues, ensure your cluster is healthy and that clients are directed to the correct shards. If a node was down and restarted, scripts loaded on it would have been lost.
Why it works: By ensuring the script is available on the shard where it’s being executed, EVALSHA will succeed. This often involves a strategy of loading scripts on all relevant nodes or using EVAL as a fallback.
6. Incorrect SHA1 Calculation
Diagnosis: The SHA1 hash of the Lua script was calculated incorrectly by the client application. This can be due to subtle differences in newline characters, whitespace, or encoding.
Fix: Double-check your SHA1 calculation method. Ensure it’s using a standard SHA1 implementation and that the input string precisely matches the script content being sent to Redis. Use redis-cli --sha1 <script_file.lua> to get the canonical SHA1 that redis-cli uses.
# Create a file with your script content, e.g., myscript.lua
echo "local v = redis.call('GET', KEYS[1]); redis.call('SET', KEYS[1], ARGV[1]); return v" > myscript.lua
# Get the SHA1
redis-cli --sha1 myscript.lua
# Output will be something like: 8a5d3100264086431577e75012a9548f0e739708
Why it works: Using the correct, consistent SHA1 hash ensures that when EVALSHA is called, Redis can find the exact script it expects in its cache.
The next error you’ll likely encounter after fixing NOSCRIPT errors is a WRONGTYPE error if your script attempts to operate on a key that has the wrong data type.