koala73/worldmonitor · error · Error
Redis EVAL failed: ${data.error}
Error message
Redis EVAL failed: ${data.error} What it means
Thrown by `rawRedisEval` in api/oauth/_refresh-recovery.ts:209 when Upstash returns HTTP 200 but the JSON body contains an `error` field, meaning the EVAL command itself failed server-side. Typical Lua failures include script compile errors, WRONGTYPE operations against mis-typed keys, or argument-shape problems — the Upstash error string is embedded in the message.
Source
Thrown at api/oauth/_refresh-recovery.ts:209
async function rawRedisEval(
script: string,
keys: string[],
args: Array<string | number>,
): Promise<unknown> {
const { url, token } = redisConfig();
const resp = await fetch(`${url}/`, {
method: 'POST',
headers: {
Authorization: `Bearer ${token}`,
'Content-Type': 'application/json',
'User-Agent': 'worldmonitor-edge/1.0',
},
body: JSON.stringify(['EVAL', script, String(keys.length), ...keys, ...args]),
signal: AbortSignal.timeout(3_000),
});
if (!resp.ok) throw new Error(`Redis HTTP ${resp.status}`);
const data = (await resp.json().catch(() => null)) as { result?: unknown; error?: string } | null;
if (data?.error) throw new Error(`Redis EVAL failed: ${data.error}`);
if (!data || !Object.prototype.hasOwnProperty.call(data, 'result')) {
throw new Error('Redis EVAL returned an invalid response');
}
return data.result;
}
function parseStoredJson(value: unknown): unknown {
if (typeof value !== 'string') throw new Error('Redis returned an invalid stored value');
try {
return JSON.parse(value);
} catch {
throw new Error('Redis returned malformed JSON');
}
}
export async function rawRedisBeginRefreshAttempt(
refreshToken: string,
attemptId: string,View on GitHub (pinned to a96956387a)
Solutions
- Read the embedded Upstash error string — it names the exact Lua/Redis failure (e.g. WRONGTYPE, script error)
- Inspect the offending keys (`oauth:refresh:<token>`, `oauth:refresh:family:attempt:*`) with `GET`/`TYPE` and delete or rewrite stale/mistyped values
- If caused by a deployment format change, flush/expire old-format keys and let the next refresh repopulate them
Defensive patterns
Strategy: try-catch
Type guard
function isRedisEvalError(e: unknown): boolean {
return e instanceof Error && e.message.startsWith('Redis EVAL failed:');
} Try / catch
try {
await beginRefreshAttempt(token, id);
} catch (e) {
if (isRedisEvalError(e)) {
// log e.message (contains the Upshade/Lua error), inspect key types; non-retryable until data is fixed
await alertOps(e);
} else throw e;
} Prevention
- Never write oauth:refresh:* keys from outside the Edge code path
- Enforce string-type keys in seed scripts; log the embedded Upstash error verbatim for diagnosis
When it happens
Trigger: The Lua refresh-attempt script hitting a WRONGTYPE because `oauth:refresh:<token>` or a family key holds a non-string Redis type; a script change deployed with mismatched KEYS/ARGV; Upstash rejecting EVAL on a read-only replica.
Common situations: Keys written by a different tool/seed script with a non-string type (hash/set) colliding with `oauth:refresh:*`; version skew between deployed Edge code and an older/newer key format; manual Redis edits via console.
Related errors
- Redis not configured
- Redis HTTP ${resp.status}
- Redis EVAL returned an invalid response
- Redis refresh-attempt consume returned an invalid response
- Redis refresh-attempt restore returned an invalid response
AI-assisted analysis of koala73/worldmonitor@a96956387a (2026-08-27).
Data as JSON: /api/errors/d23a0ea6f5169969.
Report an issue: GitHub.