koala73/worldmonitor · error · Error

Redis HTTP ${resp.status}

Error message

Redis HTTP ${resp.status}

What it means

getLargeRawJson performs a GET against the Upstash Redis HTTP API and throws a plain Error 'Redis HTTP <status>' when the HTTP response is not ok. This signals a transport/API-level failure (auth, rate limit, gateway error) rather than a missing key — a null result is returned separately for that. readCanonicalFallback callers see this as a hard read failure and should treat Redis as unavailable.

Source

Thrown at server/_shared/redis.ts:192

export async function getLargeRawJson(key: string, timeoutMs?: number): Promise<unknown | null> {
  if (process.env.LOCAL_API_MODE === 'tauri-sidecar') {
    const { sidecarCacheGet } = await import('./sidecar-cache');
    return sidecarCacheGet(key);
  }
  const url = process.env.UPSTASH_REDIS_REST_URL;
  const token = process.env.UPSTASH_REDIS_REST_TOKEN;
  if (!url || !token) return null;
  const resp = await fetch(`${url}/`, {
    method: 'POST',
    headers: {
      Authorization: `Bearer ${token}`,
      'Content-Type': 'application/json',
      'User-Agent': 'worldmonitor-server/1.0 (redis)',
    },
    body: JSON.stringify(['GET', key]),
    signal: AbortSignal.timeout(resolvePipelineTimeoutMs(timeoutMs)),
  });
  if (!resp.ok) throw new Error(`Redis HTTP ${resp.status}`);
  const data = (await resp.json()) as { result?: string | null; error?: string };
  if (data.error) throw new Error(`Redis command error: ${data.error}`);
  if (!data.result) return null;
  return unwrapEnvelope(JSON.parse(data.result)).data;
}

/**
 * Read a key's value as a raw Upstash string — no JSON.parse, no envelope unwrap.
 * Use when a seeder stores a bare scalar (e.g., a snapshot_id pointer) via
 * `['SET', key, bareString]` without JSON.stringify. getCachedJson() on these
 * keys silently returns null because JSON.parse throws on unquoted strings,
 * and the try/catch swallows the error.
 *
 * Always uses the raw (unprefixed) key — matches the seed-script write path
 * (seeders don't know about the Vercel env-prefix scheme).
 */
export async function getCachedRawString(key: string): Promise<string | null> {
  if (process.env.LOCAL_API_MODE === 'tauri-sidecar') {

View on GitHub (pinned to 9361220cc0)

Solutions

  1. Check the status code in the message: 401/403 means fix UPSTASH credentials, 429 means quota/rate limit, 5xx means retry later or check Upstash status
  2. Verify UPSTASH_REST_URL and UPSTASH_REST_TOKEN env vars are set correctly in the deployment
  3. Check the Upstash console for quota exhaustion or plan limits and upgrade/backoff as needed
  4. Retry with backoff; callers like readCanonicalFallback should fall back to the provider source when Redis is unavailable

Example fix

// before
const v = await getLargeRawJson(key); // throws on HTTP failure
// after
let v = null;
try { v = await getLargeRawJson(key); }
catch (e) { console.warn('redis read failed, falling back', e); }
Defensive patterns

Strategy: try-catch

Validate before calling

const redisConfigured = Boolean(process.env.UPSTASH_REST_URL && process.env.UPSTASH_REST_TOKEN);
if (!redisConfigured) skipRedisAndUseFallback();

Type guard

function isRedisHttpError(e: unknown): e is Error & { redis: true } {
  return e instanceof Error && /^Redis HTTP \d+$/.test(e.message);
}

Try / catch

try {
  data = await getLargeRawJson(key);
} catch (e) {
  log.warn('redis GET failed', e);
  data = null; // fall back to provider/source read
}

Prevention

When it happens

Trigger: The fetch to the Upstash REST endpoint returns a non-2xx status: 401/403 from bad or rotated UPSTASH credentials, 429 from exceeding Upstash request quota, 5xx from Upstash or an intermediate proxy, or a network-layer error surfaced as a bad status.

Common situations: Missing or stale UPSTASH_REST_URL/UPSTASH_REST_TOKEN env vars in a fresh deploy; Upstash free-tier daily command limit exhausted; Upstash incident causing 502/503; wrong region URL after migrating the database.

Related errors


AI-assisted analysis of koala73/worldmonitor@9361220cc0 (2026-09-01). Data as JSON: /api/errors/8c921dd090ecdb0c. Report an issue: GitHub.