{"record":{"id":"5e36bc8d2fdaef50","repo":"paperclipai/paperclip","slug":"opencode-api-path-returned-http-response-stat","errorCode":null,"errorMessage":"OpenCode API ${path} returned HTTP ${response.status}: ${redact(responseRaw, runtime.sensitiveValues)}","messagePattern":"OpenCode API (.+?) returned HTTP (.+?): (.+?)","errorType":"http","errorClass":null,"httpStatus":null,"severity":"error","filePath":"packages/paperclip-runner/src/drivers/opencode/opencode-server-driver.ts","lineNumber":2253,"sourceCode":"  }\n  const responseRaw = await response.text();\n  const responseFrameId = runtime.trace?.frame({\n    direction: \"provider_to_client\",\n    raw: responseRaw,\n    transport: \"http_json\",\n    nativeMethod: `${method} ${path} ${response.status}`,\n  });\n  if (!response.ok) {\n    if (responseFrameId) {\n      runtime.trace?.interpretation({\n        frameId: responseFrameId,\n        stage: \"typescript_opencode_http_parse\",\n        ruleId: `opencode.http.error.${response.status}`,\n        disposition: \"rejected\",\n        reason: `OpenCode API returned HTTP ${response.status}`,\n      });\n    }\n    throw new Error(\n      `OpenCode API ${path} returned HTTP ${response.status}: ${redact(responseRaw, runtime.sensitiveValues)}`,\n    );\n  }\n  if (response.status === 204 || !responseRaw) {\n    if (responseFrameId) {\n      runtime.trace?.interpretation({\n        frameId: responseFrameId,\n        stage: \"typescript_opencode_http_parse\",\n        ruleId: \"opencode.http.empty_success\",\n        disposition: \"operator_only\",\n        reason: \"OpenCode API returned a successful empty response\",\n      });\n    }\n    return null;\n  }\n  try {\n    const parsed = JSON.parse(responseRaw) as unknown;\n    if (responseFrameId) {","sourceCodeStart":2235,"sourceCodeEnd":2271,"githubUrl":"https://github.com/paperclipai/paperclip/blob/01ad8584922b5d85292b1723cae71fa0d9b07a19/packages/paperclip-runner/src/drivers/opencode/opencode-server-driver.ts#L2235-L2271","documentation":"Thrown when an OpenCode API request succeeds at the transport level but returns a non-2xx HTTP status. The message includes the request path, status code, and the (redacted) response body so the developer can see the server-side error reason. A trace interpretation with disposition 'rejected' is also recorded.","triggerScenarios":"Any OpenCode API endpoint replies with 4xx/5xx: 400 bad session payload, 401 bad authHeader, 404 unknown session/thread id, 409 conflicting state, 500 internal server error.","commonSituations":"Sending a threadId/sessionId from a previous server run to a restarted server (404); expired or wrong auth token (401); malformed request body after an API contract change (400); OpenCode internal error (500).","solutions":["Read the status and redacted body in the message: 404 means the session id no longer exists on the server — recreate the session.","401/403: refresh the authHeader used to build the runtime.","400: compare the request payload against the installed OpenCode version's API schema (contract may have drifted).","5xx: check OpenCode server logs and retry; persistent 5xx is a server bug or resource exhaustion."],"exampleFix":"// before\nconst res = await fetch(url, init); // 404 ignored until throw\n\n// after\nconst res = await fetch(url, init);\nif (res.status === 404) {\n  // session vanished after server restart — recreate instead of reusing id\n  providerSessionId = await createSession();\n}","handlingStrategy":"try-catch","validationCode":"if (!providerSessionId) throw new Error(\"Cannot call API before a session id exists\");","typeGuard":null,"tryCatchPattern":"try {\n  await callOpenCodeApi(`/session/${id}`, { method: \"POST\", body });\n} catch (e) {\n  if (e instanceof Error) {\n    const m = e.message.match(/returned HTTP (\\d+)/);\n    if (m && m[1] === \"404\") recreateSession(); // stale session id after server restart\n    else if (m && m[1] === \"401\") refreshAuth();\n  }\n  throw e;\n}","preventionTips":["Recreate sessions after every OpenCode server restart; never reuse old ids","Validate request payloads against the installed server version's schema","Rotate authHeader when credentials change"],"tags":["http","api","error-response","redaction"],"backgroundTag":"http-error-response","analyzedSha":"01ad8584922b5d85292b1723cae71fa0d9b07a19","analyzedAt":"2026-09-10T03:14:50.855Z","contentChangedAt":"2026-09-10T03:14:50.855Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}