Download

NOSCRIPT No matching script. Please use EVAL.

EVALSHA asked for a script by its SHA1, and this server’s script cache doesn’t have it: the cache empties on a restart, isn’t copied to replicas, and is separate on each cluster node. Load it again with SCRIPT LOAD (or send EVAL) and retry, or move the code into a function.

Redis error NOSCRIPT· Tested on Redis 8.10.2 and Valkey 8.1.10 (and temporary servers, replicas and clusters)· Updated 11 October 2026

NOSCRIPT No matching script. Please use EVAL.

What it means

EVAL sends a Lua script’s source with every call. To save sending it each time, Redis keeps every script it has seen in a cache, keyed by the SHA1 of its source, and EVALSHA <sha1> runs a script from that cache. If the cache doesn’t hold that SHA1, the server replies:

(error) NOSCRIPT No matching script. Please use EVAL.

Nothing ran. Valkey says NOSCRIPT No matching script., without the second sentence.

The script cache isn’t data: Redis doesn’t save it to disk and doesn’t send it to replicas. So a SHA1 that worked a minute ago stops working when:

  • the server restarts, including a managed service’s maintenance or a container being recreated;
  • a replica takes over in a failover: SCRIPT LOAD on the primary doesn’t reach its replicas;
  • the command goes to another cluster node: each node has its own cache, and a cluster client sends EVALSHA to the node that owns the script’s keys;
  • someone runs SCRIPT FLUSH, which empties the cache.

In a transaction, EVALSHA is queued without being checked, so the error comes back in EXEC’s reply as one of the results, and the other queued commands still run.

Common causes

  1. Scripts loaded once, at application start-up, then a restart or failover of the server while the application kept running.
  2. A Redis Cluster: the script was loaded on one node and called with keys on another.
  3. EVALSHA in a pipeline or transaction, where the client can’t catch the error and retry.
  4. A hard-coded SHA1 copied from another server or an older version of the script. Changing one character of the script changes its SHA1.

How to fix it

Fall back to EVAL, then use EVALSHA again

The usual pattern is: call EVALSHA; on NOSCRIPT, call EVAL with the full source (which also caches it) or SCRIPT LOAD it and retry. Most client libraries have a script helper that does this for you; use it rather than calling EVALSHA directly.

SCRIPT EXISTS <sha1>       # 1 if cached here, 0 if not
SCRIPT LOAD "<source>"     # caches it, returns the SHA1

In a pipeline or transaction, send EVAL

A NOSCRIPT inside a pipeline or MULTI can’t be retried in place. Send EVAL with the source there, or run SCRIPT LOAD on that connection first.

In a cluster, load the script on every primary

Run SCRIPT LOAD on each primary (redis-cli --cluster call <host>:<port> SCRIPT LOAD "<source>" sends a command to every node), and again after a failover. Or rely on the EVAL fallback above, which caches the script on whichever node runs it.

Or use a function instead

Redis 7.0 added functions: FUNCTION LOAD stores a library of Lua functions that is saved with the data, copied to replicas, and called by name with FCALL, so there’s no SHA1 to go missing. Valkey has functions too.

FUNCTION LOAD "#!lua name=mylib
redis.register_function('hello', function(keys, args) return 'hi' end)"
FCALL hello 0

A function that only reads, registered with flags={'no-writes'}, can run on a replica with FCALL_RO.

Reproduce it

On the Redis 8.10.2 and Valkey 8.1.10 test servers, a SHA1 that was never loaded:

EVALSHA ffffffffffffffffffffffffffffffffffffffff 0
(error) NOSCRIPT No matching script. Please use EVAL.

Valkey replied (error) NOSCRIPT No matching script. Both answered SCRIPT EXISTS with 1) (integer) 0. In a transaction on Redis, the error came back from EXEC, and the commands around it ran:

MULTI
OK
SET seo:err:a 1
QUEUED
EVALSHA ffffffffffffffffffffffffffffffffffffffff 0
QUEUED
INCR seo:err:a
QUEUED
EXEC
1) OK
2) (error) NOSCRIPT No matching script. Please use EVAL.
3) (integer) 2

A restart. On a temporary Redis 8.10.2 container, SCRIPT LOAD "return 1" returned e0e1f9fabfc9d4800c877a703b823ac0578ff8db and EVALSHA of it returned (integer) 1. After docker restart, the same EVALSHA got NOSCRIPT No matching script. Please use EVAL.

A replica. With a second temporary container replicating the first (master_link_status:up), the script loaded on the primary wasn’t on the replica: SCRIPT EXISTS replied 1) (integer) 0 and EVALSHA got NOSCRIPT. A function loaded on the primary with FUNCTION LOAD was on the replica a second later (FCALL_RO hello 0 returned "hi" there), and still on the primary after a restart.

A cluster. A temporary three-node Redis 8.10.2 cluster (slots 0–5460 on port 6381, 5461–10922 on 6382, 10923–16383 on 6383). The script was loaded on 6381 only:

$ redis-cli -p 6381 SCRIPT LOAD "return redis.call('GET', KEYS[1])"
d3c21d0c2b9ca22f82737626a27bcaf5d288f99f

Then, in one redis-cli -c -p 6381 session, SET bar 1 and the script on bar and on user:1:

OK
"1"
-> Redirected to slot [10778] located at 127.0.0.1:6382
(error) NOSCRIPT No matching script. Please use EVAL.

bar is in slot 5061, on 6381; user:1 is in slot 10778, on 6382, which had never seen the script. Loading it on every node fixed it; the EVALSHA on user:1 then replied (nil) (no such key):

$ redis-cli --cluster call 127.0.0.1:6381 SCRIPT LOAD "return redis.call('GET', KEYS[1])"
>>> Calling SCRIPT LOAD return redis.call('GET', KEYS[1])
127.0.0.1:6381: d3c21d0c2b9ca22f82737626a27bcaf5d288f99f
127.0.0.1:6382: d3c21d0c2b9ca22f82737626a27bcaf5d288f99f
127.0.0.1:6383: d3c21d0c2b9ca22f82737626a27bcaf5d288f99f

In Inlet

Query tabs take redis-cli commands, so SCRIPT EXISTS, SCRIPT LOAD, EVAL, EVALSHA and FCALL run there; Stop kills a script that runs too long. On a cluster (Pro), Inlet sends each command to the node that holds its keys, so a script loaded through one node may be missing on another, as above. When the server replies NOSCRIPT, Inlet shows its message and links to this page.

Inlet: a database client for the Mac

One native app for PostgreSQL, MySQL, SQL Server, SQLite, MongoDB and Redis. It explains errors where they happen, holds your edits until you save them, and keeps production read-only until you say so.

Version 0.1.0 · macOS 26 Tahoe or later · Apple silicon and Intel