Skip to content
DevOps AI ToolKit
Newsletter
All guides
AI for Redis By James Joyner IV · · 8 min read

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 EVALSHANOSCRIPTEVAL fallback that makes this self-healing.

Symptoms

  • EVALSHA fails with NOSCRIPT while EVAL of 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 → catch NOSCRIPTEVAL fallback; 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 LOAD as 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:

  1. The server restarted and cleared the cache.
  2. SCRIPT FLUSH was called.
  3. A failover put you on a node that never loaded the script.
  4. A client that caches the SHA without an EVAL fallback.

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.

Free download · 368-page PDF

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.