{"record":{"id":"d23a0ea6f5169969","repo":"koala73/worldmonitor","slug":"redis-eval-failed-data-error","errorCode":null,"errorMessage":"Redis EVAL failed: ${data.error}","messagePattern":"Redis EVAL failed: (.+?)","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"api/oauth/_refresh-recovery.ts","lineNumber":209,"sourceCode":"async function rawRedisEval(\n  script: string,\n  keys: string[],\n  args: Array<string | number>,\n): Promise<unknown> {\n  const { url, token } = redisConfig();\n  const resp = await fetch(`${url}/`, {\n    method: 'POST',\n    headers: {\n      Authorization: `Bearer ${token}`,\n      'Content-Type': 'application/json',\n      'User-Agent': 'worldmonitor-edge/1.0',\n    },\n    body: JSON.stringify(['EVAL', script, String(keys.length), ...keys, ...args]),\n    signal: AbortSignal.timeout(3_000),\n  });\n  if (!resp.ok) throw new Error(`Redis HTTP ${resp.status}`);\n  const data = (await resp.json().catch(() => null)) as { result?: unknown; error?: string } | null;\n  if (data?.error) throw new Error(`Redis EVAL failed: ${data.error}`);\n  if (!data || !Object.prototype.hasOwnProperty.call(data, 'result')) {\n    throw new Error('Redis EVAL returned an invalid response');\n  }\n  return data.result;\n}\n\nfunction parseStoredJson(value: unknown): unknown {\n  if (typeof value !== 'string') throw new Error('Redis returned an invalid stored value');\n  try {\n    return JSON.parse(value);\n  } catch {\n    throw new Error('Redis returned malformed JSON');\n  }\n}\n\nexport async function rawRedisBeginRefreshAttempt(\n  refreshToken: string,\n  attemptId: string,","sourceCodeStart":191,"sourceCodeEnd":227,"githubUrl":"https://github.com/koala73/worldmonitor/blob/a96956387a927b8cd7aa34b0c41fca357e746be9/api/oauth/_refresh-recovery.ts#L191-L227","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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"],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":null,"typeGuard":"function isRedisEvalError(e: unknown): boolean {\n  return e instanceof Error && e.message.startsWith('Redis EVAL failed:');\n}","tryCatchPattern":"try {\n  await beginRefreshAttempt(token, id);\n} catch (e) {\n  if (isRedisEvalError(e)) {\n    // log e.message (contains the Upshade/Lua error), inspect key types; non-retryable until data is fixed\n    await alertOps(e);\n  } else throw e;\n}","preventionTips":["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"],"tags":["redis","upstash","lua","eval","oauth","wrongtype"],"backgroundTag":"redis-eval-script-error","analyzedSha":"a96956387a927b8cd7aa34b0c41fca357e746be9","analyzedAt":"2026-08-27T19:53:08.521Z","schemaVersion":2},"datasetVersion":"2026-08-31T04:17:50.494Z"}