Download

ERR user_script:1: Lua script errors in Redis

A Lua script run with EVAL, EVALSHA or FCALL failed: user_script:1 is the line. Most often it used a global variable (Redis forbids them), did arithmetic on the false that redis.call returns for a missing key, or passed nil or a table to redis.call. Commands before the error stay done.

Redis error ERR· Tested on Redis 8.10.2 and Valkey 8.1.10· Updated 11 October 2026

ERR user_script:1: Script attempted to access nonexistent global variable 'foo' script: 47e30a5d10d5694f99208f9adc4fe3bf2450edbd, on @user_script:1.

What it means

The script you sent with EVAL or EVALSHA (or a function called with FCALL) stopped with a Lua error. Redis reports it as an ERR, starting with where it happened and ending with which script:

(error) ERR user_script:1: Script attempted to access nonexistent global variable 'foo' script: 47e30a5d10d5694f99208f9adc4fe3bf2450edbd, on @user_script:1.
  • user_script:1: is the line of the script (functions say user_function:<line>:).
  • script: 47e3… is the script’s SHA1, the one EVALSHA uses; for a function it’s the function’s name.

A script isn’t a transaction that rolls back: anything it wrote before the failing line stays written. Redis 6.2 and older word runtime errors differently, ERR Error running script (call to f_<sha1>): ….

The messages you’ll meet most:

MessageWhat happened
Script attempted to access nonexistent global variable 'x'The script read a name that was never declared: a typo, or a variable defined nowhere
Attempt to modify a readonly tableThe script assigned a global (x = 1); scripts must use local
attempt to perform arithmetic on local 'n' (a boolean value)n came from redis.call('GET', …) on a missing key, which gives false, not nil
attempt to perform arithmetic on field '?' (a string value)Arithmetic on text that isn’t a number, such as an ARGV value of abc
attempt to index local 't' (a nil value)t.name where t is nil
attempt to concatenate a nil value.. with a nil, often a missing ARGV[n]
Error compiling script (new function): user_script:1: …A Lua syntax error; nothing ran
Lua redis lib command arguments must be strings or integersredis.call was given a table, a boolean or a nil (such as KEYS[1] when no key was passed)
Please specify at least one argument for this redis lib callredis.call() with nothing in it

Errors from the commands a script runs keep their own code and wording, with the script’s SHA1 and line added: a GET on a hash inside a script is still WRONGTYPE, and INCR on a word is still not an integer.

Common causes

  1. A missing local. Redis protects the global table: reading an undeclared name fails with “nonexistent global variable”, and writing one fails with “readonly table”.
  2. Treating a missing key as nil. redis.call('GET', KEYS[1]) returns false for a missing key (a Redis null becomes Lua’s false), so if v == nil never fires and v + 1 fails.
  3. Strings used as numbers. Everything in KEYS and ARGV, and every reply from GET, is a string. Lua converts digits automatically in arithmetic, but not text, and comparing a string with a number fails (attempt to compare number with string).
  4. A missing argument: the script reads ARGV[2] but the caller sent one, so it’s nil.
  5. A Lua syntax error, often from building the script by string concatenation in your code.

How to fix it

Declare every variable with local

local count = tonumber(redis.call('GET', KEYS[1]) or '0')
return count + tonumber(ARGV[1])

Handle missing keys as false

local v = redis.call('GET', KEYS[1])
if not v then
  return nil   -- or a default
end

Convert and check arguments

Use tonumber(ARGV[1]), and check the result: tonumber('abc') is nil, so local n = tonumber(ARGV[1]); if not n then return redis.error_reply('ERR amount must be a number') end turns a confusing Lua error into a clear one ((error) ERR amount must be a number when called with abc). Pass every key in KEYS and every value in ARGV; never build key names inside the script.

Find the line

The number after user_script: is the line. For anything longer than a few lines, Redis’s Lua debugger steps through a script without touching your data (by default it runs in a forked copy that’s thrown away):

redis-cli --ldb --eval ./myscript.lua key1 key2 , arg1 arg2

Use it on a development server: in the default mode it forks the server for each session.

Catch errors you expect

redis.pcall returns a command’s error to the script as a table instead of stopping it, so the script can decide what to do. redis.error_reply('MYERR …') returns your own error, code included.

Reproduce it

Each script below ran with EVAL … 0 (or with the keys shown) on Redis 8.10.2 and Valkey 8.1.10, in database 15; both gave the same messages and SHA1s unless noted. A global:

EVAL "return foo" 0
(error) ERR user_script:1: Script attempted to access nonexistent global variable 'foo' script: 47e30a5d10d5694f99208f9adc4fe3bf2450edbd, on @user_script:1.
EVAL "x = 1" 0
(error) ERR user_script:1: Attempt to modify a readonly table script: 34bce5f775de97f557a34088509c8bfe1ea17e52, on @user_script:1.

A missing key read with GET, then used as a number:

EVAL "local n = redis.call('GET', KEYS[1]) return n + 1" 1 seo:err:missing
(error) ERR user_script:1: attempt to perform arithmetic on local 'n' (a boolean value) script: 8a50c244a122e67dcec077dc0aa03549f5b8bd5f, on @user_script:1.

A write before the error isn’t undone:

EVAL "redis.call('SET', KEYS[1], 'written') return foo" 1 seo:err:w
(error) ERR user_script:1: Script attempted to access nonexistent global variable 'foo' script: 8c84fa2df321967d3d42a3db41754a94f80359fb, on @user_script:1.
GET seo:err:w
"written"

Compile errors (nothing ran):

EVAL "return (" 0
(error) ERR Error compiling script (new function): user_script:1: unexpected symbol near '<eof>'
EVAL "retrun 1" 0
(error) ERR Error compiling script (new function): user_script:1: '=' expected near '1'

Arguments and values:

EVAL "return ARGV[1] + 1" 0 abc
(error) ERR user_script:1: attempt to perform arithmetic on field '?' (a string value) script: 84834ee62a493ae7cb74fa5841a3a02222e583ba, on @user_script:1.
EVAL "return 'a' .. nil" 0
(error) ERR user_script:1: attempt to concatenate a nil value script: a954e0524e4e64a9f26274ffcefea47159ca7c15, on @user_script:1.
EVAL "local t = nil return t.name" 0
(error) ERR user_script:1: attempt to index local 't' (a nil value) script: 0fda25fc4233a6d8067d369b564c60e890b6ad3e, on @user_script:1.
EVAL "return redis.call('SET', KEYS[1], nil)" 1 seo:err:k
(error) ERR Lua redis lib command arguments must be strings or integers script: ccc37fbed5e464fd504faa7028bb4676f0663acb, on @user_script:1.

Valkey words the last one ERR Command arguments must be strings or integers, and redis.call() with nothing in it ERR Please specify at least one argument for this call (Redis: … for this redis lib call). error('boom') gave ERR user_script:1: boom script: …, and return redis.error_reply('MYERR something went wrong') gave (error) MYERR something went wrong, with its own code and no suffix. redis.pcall('INCR', KEYS[1]) on a key holding hello returned (error) ERR value is not an integer or out of range without the script suffix.

A function on a temporary Redis 8.10.2 server, FCALL broken 0, where broken returned foo:

ERR user_function:2: Script attempted to access nonexistent global variable 'foo' script: broken, on @user_function:2.

In Inlet

Query tabs take redis-cli commands, so you can run EVAL with the script in quotes and see the reply as a table, or the error. Stop kills a script that runs too long, as long as it hasn’t written anything yet (see BUSY). When a script fails, Inlet shows the server’s 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