koala73/worldmonitor · error · Error
Redis HTTP ${resp.status}
Error message
Redis HTTP ${resp.status} What it means
Thrown by `rawRedisEval` in api/oauth/_refresh-recovery.ts:207 when the Upstash Redis REST API answers the EVAL POST with a non-2xx HTTP status. It signals a transport/auth-level failure rather than a script-level one (which comes back 200 with an `error` field). The fetch has a 3-second AbortSignal timeout, so timeouts surface as AbortError, not this message.
Source
Thrown at api/oauth/_refresh-recovery.ts:207
}
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(View on GitHub (pinned to a96956387a)
Solutions
- Check the status: 401/403 means fix `UPSTASH_REDIS_REST_TOKEN`; 404 means fix `UPSTASH_REDIS_REST_URL`; 429 means rate limit — reduce call frequency or upgrade plan; 5xx is a transient Upstash issue — retry
- Verify the URL points to the correct live Upstash database and the token belongs to it
- Retry the OAuth refresh; the recovery flow is designed so a retryable failure does not lose the refresh token (restore/replay protection handles it)
Defensive patterns
Strategy: retry
Type guard
function isRedisHttpError(e: unknown): e is Error & { status?: number } {
const m = /^Redis HTTP (\d+)$/.exec(e instanceof Error ? e.message : '');
return m !== null;
} Try / catch
try {
await beginRefreshAttempt(token, id);
} catch (e) {
if (isRedisHttpError(e)) {
const status = Number(/\d+$/.exec(e.message)[0]);
if (status === 429 || status >= 500) await retryWithBackoff(); // transient
else reportConfigIssue(e); // 401/403/404 — fix credentials/URL
} else throw e;
} Prevention
- Retry only 429/5xx with backoff; treat 401/404 as configuration failures
- Monitor Upstash status and rate-limit headers; keep credentials in sync on rotation
When it happens
Trigger: An expired or wrong `UPSTASH_REDIS_REST_TOKEN` (401), a wrong `UPSTASH_REDIS_REST_URL` (404), rate limiting (429), or Upstash/platform 5xx outages during an OAuth refresh attempt EVAL call.
Common situations: Rotated Upstash credentials not updated in Vercel env; pointing the URL at a deleted database; hitting Upstash free-tier rate limits during refresh storms; transient Upstash incidents.
Related errors
- Redis not configured
- Redis EVAL failed: ${data.error}
- 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/7b7ff6a6d7fb74d1.
Report an issue: GitHub.