{"record":{"id":"0bfd28a59f4fe152","repo":"justjavac/wechat-miniapp-radar","slug":"upstash-request-failed-with-response-status","errorCode":null,"errorMessage":"Upstash request failed with ${response.status}","messagePattern":"Upstash request failed with (.+?)","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"warning","filePath":"lib/upstash.ts","lineNumber":51,"sourceCode":"export function hasUpstashRedis() {\n  return Boolean(getUpstashRedisConfig());\n}\n\nexport async function upstashCommand<T>(command: Array<string | number>): Promise<T | null> {\n  const config = getUpstashRedisConfig();\n  if (!config) return null;\n\n  const response = await fetch(config.url, {\n    method: \"POST\",\n    headers: {\n      authorization: `Bearer ${config.token}`,\n      \"content-type\": \"application/json\"\n    },\n    body: JSON.stringify(command)\n  });\n\n  if (!response.ok) {\n    throw new Error(`Upstash request failed with ${response.status}`);\n  }\n\n  const payload = (await response.json()) as UpstashResponse<T>;\n  if (payload.error) {\n    throw new Error(payload.error);\n  }\n\n  return payload.result ?? null;\n}\n","sourceCodeStart":33,"sourceCodeEnd":61,"githubUrl":"https://github.com/justjavac/wechat-miniapp-radar/blob/02a010ecea0320b7aa975bb62a5dde271ae630c9/lib/upstash.ts#L33-L61","documentation":"Thrown by upstashCommand() in lib/upstash.ts when the REST POST returns a non-2xx status. It formats only the status code (`Upstash request failed with <status>`) without the body. If getUpstashRedisConfig() is null (neither the UPSTASH_REDIS_REST_* nor the KV_REST_API_* pair is set), the function returns null early and never throws, so this error implies the integration IS configured but the endpoint rejected the request. Per project guidance Upstash is optional and callers should fall back to in-memory when it fails.","triggerScenarios":"401/403 wrong or revoked token (UPSTASH_REDIS_REST_TOKEN / KV_REST_API_TOKEN); 404 from a wrong UPSTASH_REDIS_REST_URL (e.g. using the redis:// host instead of the https REST endpoint); 429 daily command quota exceeded on the free tier; provider 5xx; URL pasted with a wrong region.","commonSituations":"Copied the redis:// connection string into UPSTASH_REDIS_REST_URL instead of the REST URL; token rotated in the Upstash dashboard but not in the Vercel env; free daily limit hit by Advisor caching or rate-limit traffic; Vercel KV env vars injected under a different name than KV_REST_API_URL/KV_REST_API_TOKEN.","solutions":["Use the Upstash REST URL (https://<id>.upstash.io) and its REST token, not the redis:// string and DB password.","Verify the pair with EXPECT_UPSTASH_REDIS=1 npm run integrations:verify.","For 429, check the Upstash daily usage dashboard and raise the plan or reduce call frequency.","Wrap the call in try-catch and degrade to the in-memory fallback (the documented behavior when Upstash is unavailable)."],"exampleFix":"// before\nconst cached = await upstashCommand<string>(['GET', key]); // throws on 401\n\n// after\nlet cached: string | null = null;\ntry {\n  cached = await upstashCommand<string>(['GET', key]);\n} catch (error) {\n  cached = memoryCache.get(key) ?? null;\n}","handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"try {\n  const value = await upstashCommand<T>(command);\n  return value;\n} catch (error) {\n  // error.message is 'Upstash request failed with <status>'\n  return inMemoryFallback();\n}","preventionTips":["Treat Upstash as optional: every call site must have an in-memory fallback.","Store the REST URL and token as a pair; mixing the redis:// host with a REST token is the most common 404/401.","Run EXPECT_UPSTASH_REDIS=1 npm run integrations:verify before relying on it."],"tags":["redis","upstash","network","http"],"backgroundTag":null,"analyzedSha":"02a010ecea0320b7aa975bb62a5dde271ae630c9","analyzedAt":"2026-08-12T16:16:33.227Z","schemaVersion":2},"datasetVersion":"2026-08-12T18:17:37.767Z"}