{"record":{"id":"5c9140a226c3cdbd","repo":"paperclipai/paperclip","slug":"api-error-response-status-message","errorCode":null,"errorMessage":"API error ${response.status}: ${message}","messagePattern":"API error (.+?): (.+?)","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"cli/src/commands/client/issue.ts","lineNumber":1439,"sourceCode":"): Promise<Buffer> {\n  const response = await fetch(buildApiUrl(apiBase, apiPath`/api/attachments/${attachmentId}/content`), {\n    headers: apiKey ? { authorization: `Bearer ${apiKey}` } : undefined,\n  });\n  if (!response.ok) {\n    await parseFetchResponse(response);\n  }\n  return Buffer.from(await response.arrayBuffer());\n}\n\nasync function parseFetchResponse(response: Response): Promise<unknown> {\n  const text = await response.text();\n  const parsed = text.trim() ? safeJson(text) : null;\n  if (!response.ok) {\n    const message =\n      typeof parsed === \"object\" && parsed !== null && \"error\" in parsed && typeof parsed.error === \"string\"\n        ? parsed.error\n        : `Request failed with status ${response.status}`;\n    throw new Error(`API error ${response.status}: ${message}`);\n  }\n  return parsed;\n}\n\nfunction safeJson(text: string): unknown {\n  try {\n    return JSON.parse(text) as unknown;\n  } catch {\n    return text;\n  }\n}\n","sourceCodeStart":1421,"sourceCodeEnd":1451,"githubUrl":"https://github.com/paperclipai/paperclip/blob/67001ec6eb96ae601aa27bc91d9b2415d665334a/cli/src/commands/client/issue.ts#L1421-L1451","documentation":"parseFetchResponse throws when response.ok is false. It prefers a server-provided parsed.error string; otherwise it falls back to a status-code message. This is the generic HTTP-error path for issue command fetches.","triggerScenarios":"Any non-2xx response from an issue endpoint: 400 bad request, 401 unauthorized, 403 forbidden, 404 not found, 409 conflict, 422 validation, 500 server error.","commonSituations":"Expired/invalid API key (401); wrong issue id (404); validation failure (422); server outage (5xx); rate limiting.","solutions":["Inspect err.message: the leading number is the status code, the rest is the server message.","For 401/403, refresh or re-scope the API key.","For 404, verify the issue id and company scope.","For 5xx, check API health and retry."],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"try {\n  const data = await parseFetchResponse(response);\n} catch (err) {\n  const msg = err instanceof Error ? err.message : String(err);\n  const status = Number(/^(\\d{3})/.exec(msg)?.[1]);\n  if (status === 401) await refreshAuthToken();\n  if (status >= 500) {/* retry with backoff */}\n  throw err;\n}","preventionTips":["Always inspect the leading status code in the thrown message.","Refresh tokens before they expire to avoid 401s."],"tags":["cli","issue","api","http"],"backgroundTag":null,"analyzedSha":"67001ec6eb96ae601aa27bc91d9b2415d665334a","analyzedAt":"2026-08-12T12:05:45.408Z","schemaVersion":2},"datasetVersion":"2026-08-12T18:17:37.767Z"}