From 2fd155e31da91ecbe2d3f3f8475eee485805cd41 Mon Sep 17 00:00:00 2001 From: Nil <22560738+NilPuig@users.noreply.github.com> Date: Sat, 7 Feb 2026 15:13:58 +0800 Subject: [PATCH] Fix nil guard for MEMORY USAGE in memoryUsageCmd Lua script MEMORY USAGE returns nil for keys that no longer exist (e.g., expired or deleted task keys). In Lua, nil is converted to false (a boolean). The script then attempts arithmetic on this boolean value, causing: ERR user_script:30: attempt to perform arithmetic on local 'bytes' (a boolean value) This breaks the /api/queues endpoint in asynqmon, showing "Could not retrieve queues live data" in the UI. The fix adds nil guards around all three MEMORY USAGE calls on task keys, and a divide-by-zero guard on agg_task_sample_size. Tested in production with Redis 7.2 and asynq v0.25.1 worker. Fixes #728 Related to #901 --- internal/rdb/inspect.go | 20 ++++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) diff --git a/internal/rdb/inspect.go b/internal/rdb/inspect.go index 4bd7975..8a8be62 100644 --- a/internal/rdb/inspect.go +++ b/internal/rdb/inspect.go @@ -264,7 +264,9 @@ for i=1,2 do if (table.getn(ids) > 0) then for _, id in ipairs(ids) do local bytes = redis.call("MEMORY", "USAGE", ARGV[1] .. id) - sample_total = sample_total + bytes + if bytes then + sample_total = sample_total + bytes + end end local n = redis.call("LLEN", KEYS[i]) local avg = sample_total / table.getn(ids) @@ -281,7 +283,9 @@ for i=3,6 do if (table.getn(ids) > 0) then for _, id in ipairs(ids) do local bytes = redis.call("MEMORY", "USAGE", ARGV[1] .. id) - sample_total = sample_total + bytes + if bytes then + sample_total = sample_total + bytes + end end local n = redis.call("ZCARD", KEYS[i]) local avg = sample_total / table.getn(ids) @@ -304,13 +308,17 @@ if table.getn(groups) > 0 then local ids = redis.call("ZRANGE", group_key, 0, sample_size - 1) for _, id in ipairs(ids) do local bytes = redis.call("MEMORY", "USAGE", ARGV[1] .. id) - agg_task_sample_total = agg_task_sample_total + bytes - agg_task_sample_size = agg_task_sample_size + 1 + if bytes then + agg_task_sample_total = agg_task_sample_total + bytes + agg_task_sample_size = agg_task_sample_size + 1 + end end end end - local avg = agg_task_sample_total / agg_task_sample_size - memusg = memusg + (avg * agg_task_count) + if agg_task_sample_size > 0 then + local avg = agg_task_sample_total / agg_task_sample_size + memusg = memusg + (avg * agg_task_count) + end end return memusg `)