{"record":{"id":"d7cd61c8c2418f30","repo":"jackwener/OpenCLI","slug":"weread-official-apiname-http-response-status","errorCode":null,"errorMessage":"weread-official ${apiName} HTTP ${response.status}","messagePattern":"weread-official (.+?) HTTP (.+?)","errorType":"exception","errorClass":"CommandExecutionError","httpStatus":null,"severity":"error","filePath":"clis/weread-official/utils.js","lineNumber":105,"sourceCode":"                'Content-Type': 'application/json',\n            },\n            body: JSON.stringify(body),\n            signal: controller.signal,\n        });\n    }\n    catch (error) {\n        if (error?.name === 'AbortError') {\n            throw new TimeoutError(`weread-official ${apiName}`, Math.round(timeoutMs / 1000));\n        }\n        const detail = error instanceof Error ? error.message : String(error);\n        throw new CommandExecutionError(`weread-official ${apiName} request failed`, detail);\n    }\n    finally {\n        clearTimeout(timer);\n    }\n\n    if (!response.ok) {\n        throw new CommandExecutionError(\n            `weread-official ${apiName} HTTP ${response.status}`,\n            'Check WeRead gateway availability and that WEREAD_API_KEY is still valid.',\n        );\n    }\n\n    let payload;\n    try {\n        payload = await response.json();\n    }\n    catch (error) {\n        const detail = error instanceof Error ? error.message : String(error);\n        throw new CommandExecutionError(`weread-official ${apiName} returned invalid JSON`, detail);\n    }\n\n    if (payload && typeof payload === 'object' && payload.upgrade_info) {\n        const info = payload.upgrade_info;\n        const required = info?.required_version ?? info?.version ?? 'unknown';\n        const message = info?.message ?? 'WeRead skill version is outdated';","sourceCodeStart":87,"sourceCodeEnd":123,"githubUrl":"https://github.com/jackwener/OpenCLI/blob/49907e53dc3ade5c223ff0c4c2c2785687cec4e6/clis/weread-official/utils.js#L87-L123","documentation":"The gateway responded with a non-2xx HTTP status. callGateway raises CommandExecutionError naming the api and status, with the hint that either the gateway is down or WEREAD_API_KEY is no longer valid.","triggerScenarios":"HTTP 401/403 from an expired or revoked WEREAD_API_KEY; HTTP 502/503 from gateway maintenance or outage; HTTP 404 after the gateway path changed; HTTP 429 rate limiting.","commonSituations":"Key rotated upstream while a cached key remains in the environment; gateway deployed behind a new path; burst scripts tripping rate limits.","solutions":["Confirm WEREAD_API_KEY is set and current; regenerate and re-export if rejected.","Re-run the command to check for transient 5xx.","Check gateway status / maintenance announcements.","Back off on 429 and retry later; throttle request rate."],"exampleFix":"// before\nexport WEREAD_API_KEY=old_key\n// after (regenerate at the WeRead console, then)\nexport WEREAD_API_KEY=<freshly_generated_key>","handlingStrategy":"retry","validationCode":"if (!process.env.WEREAD_API_KEY) throw new Error('WEREAD_API_KEY is not set — export it before calling the gateway');","typeGuard":"const isHttpError = (e) => e instanceof CommandExecutionError && /HTTP \\d{3}/.test(e.message);","tryCatchPattern":"try {\n  return await callGateway(apiName, params);\n} catch (e) {\n  const m = e instanceof CommandExecutionError && /HTTP (\\d{3})/.exec(e.message);\n  if (m && ['502','503','504'].includes(m[1])) {\n    await sleep(2000); return callGateway(apiName, params); // transient\n  }\n  if (m && m[1] === '429') { await sleep(60000); return callGateway(apiName, params); }\n  throw e;\n}","preventionTips":["Refresh WEREAD_API_KEY before long-running jobs","Retry only 5xx/429; never retry 401/403","Throttle request rates in batch scripts","Subscribe to gateway status announcements"],"tags":["http","auth","api-gateway"],"backgroundTag":"http-error-response","analyzedSha":"49907e53dc3ade5c223ff0c4c2c2785687cec4e6","analyzedAt":"2026-08-29T08:14:47.543Z","schemaVersion":2},"datasetVersion":"2026-08-29T12:17:43.993Z"}