{"record":{"id":"a7933dd3bb2c982a","repo":"koala73/worldmonitor","slug":"redis-not-configured","errorCode":null,"errorMessage":"Redis not configured","messagePattern":"Redis not configured","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"critical","filePath":"api/oauth/_refresh-recovery.ts","lineNumber":187,"sourceCode":"  return false;\n}\n\nexport async function finalizeRefreshAttempt(\n  deps: Pick<RefreshRecoveryDeps, 'redisFinalizeRefreshAttempt'>,\n  refreshToken: string,\n  attemptValue: string,\n): Promise<boolean> {\n  try {\n    return await deps.redisFinalizeRefreshAttempt(refreshToken, attemptValue);\n  } catch {\n    return false;\n  }\n}\n\nfunction redisConfig(): { url: string; token: string } {\n  const url = process.env.UPSTASH_REDIS_REST_URL;\n  const token = process.env.UPSTASH_REDIS_REST_TOKEN;\n  if (!url || !token) throw new Error('Redis not configured');\n  return { url, token };\n}\n\nasync 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),","sourceCodeStart":169,"sourceCodeEnd":205,"githubUrl":"https://github.com/koala73/worldmonitor/blob/a96956387a927b8cd7aa34b0c41fca357e746be9/api/oauth/_refresh-recovery.ts#L169-L205","documentation":"Thrown by `redisConfig()` in api/oauth/_refresh-recovery.ts:187 when either `UPSTASH_REDIS_REST_URL` or `UPSTASH_REDIS_REST_TOKEN` is missing from the environment. The OAuth refresh-recovery flow on Vercel Edge needs these to reach Upstash Redis over HTTP for atomic compare-and-set operations protecting refresh-token replay. Without them, no Redis call can even be attempted.","triggerScenarios":"Any invocation of `rawRedisBeginRefreshAttempt`, `rawRedisRestoreRefreshAttempt`, or `rawRedisFinalizeRefreshAttempt` (i.e. an OAuth token refresh with recovery handling) when one or both env vars are unset in the Edge runtime.","commonSituations":"Deploying the Edge functions without linking the Upstash env vars; local development lacking `.env.local`; rotating/upstairs Redis credentials and only setting one var; targeting a preview environment that never received the secrets.","solutions":["Set both `UPSTASH_REDIS_REST_URL` and `UPSTASH_REDIS_REST_TOKEN` in the deployment environment (Vercel project env or local .env/.env.local)","Verify they are present in the environment the Edge function actually runs in (production vs preview vs dev), not just the shell","After fixing, confirm the refresh flow succeeds; callers already degrade gracefully because finalize/protect paths catch these errors"],"exampleFix":"# before (env missing)\n# after\nUPSTASH_REDIS_REST_URL=https://your-db.upstash.io\nUPSTASH_REDIS_REST_TOKEN=AXX...","handlingStrategy":"fallback","validationCode":"const hasRedis = Boolean(process.env.UPSTASH_REDIS_REST_URL && process.env.UPSTASH_REDIS_REST_TOKEN);\nif (!hasRedis) {\n  // skip recovery path or fail fast with a config error before calling refresh recovery\n}","typeGuard":null,"tryCatchPattern":"try {\n  await beginRefreshAttempt(token, id);\n} catch (e) {\n  if (e instanceof Error && e.message === 'Redis not configured') {\n    // config problem: surface a deployment error, do not retry\n  } else throw e;\n}","preventionTips":["Add a startup/health check asserting UPSTASH_REDIS_REST_URL and UPSTASH_REDIS_REST_TOKEN are set in every environment running OAuth Edge code","Include both vars in preview-environment templates and CI secret checks"],"tags":["redis","upstash","environment-variables","oauth","edge-functions","config"],"backgroundTag":"missing-env-var","analyzedSha":"a96956387a927b8cd7aa34b0c41fca357e746be9","analyzedAt":"2026-08-27T19:53:08.521Z","contentChangedAt":"2026-08-27T19:53:08.521Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}