{"record":{"id":"1ed14e8e93702c55","repo":"thedotmack/claude-mem","slug":"anthropic-api-error-response-status-bodytext","errorCode":null,"errorMessage":"Anthropic API error: ${response.status} - ${bodyText}","messagePattern":"Anthropic API error: (.+?) - (.+?)","errorType":"exception","errorClass":"ServerClassifiedProviderError","httpStatus":null,"severity":"error","filePath":"src/server/generation/providers/ClaudeObservationProvider.ts","lineNumber":85,"sourceCode":"        rawText: '<skip_summary reason=\"all_events_private\" />',\n        providerLabel: this.providerLabel,\n        modelId: this.model,\n      };\n    }\n\n    let response: Response;\n    try {\n      response = await this.postMessages(prompt, signal);\n    } catch (networkError) {\n      const err = networkError instanceof Error ? networkError : new Error(String(networkError));\n      throw classifyClaudeServerError({\n        cause: err,\n      });\n    }\n\n    if (!response.ok) {\n      const bodyText = await safeReadBody(response);\n      throw classifyClaudeServerError({\n        status: response.status,\n        bodyText,\n        headers: response.headers,\n        cause: new Error(`Anthropic API error: ${response.status} - ${bodyText}`),\n      });\n    }\n\n    let data: AnthropicMessagesResponse;\n    try {\n      data = (await response.json()) as AnthropicMessagesResponse;\n    } catch (parseError) {\n      const err = parseError instanceof Error ? parseError : new Error(String(parseError));\n      throw new ServerClassifiedProviderError('Anthropic returned invalid JSON', {\n        kind: 'parse_error',\n        cause: err,\n      });\n    }\n","sourceCodeStart":67,"sourceCodeEnd":103,"githubUrl":"https://github.com/thedotmack/claude-mem/blob/d8bc9755e74915e5c3b999181e10a67c889bce2a/src/server/generation/providers/ClaudeObservationProvider.ts#L67-L103","documentation":"Anthropic returned a non-2xx HTTP status to the ClaudeObservationProvider. The provider reads the response body and passes status, body text, and headers to classifyClaudeServerError, attaching cause `Anthropic API error: <status> - <body>`. The classifier maps statuses (401 invalid key, 429 rate limit, 5xx/overloaded retryable, 4xx unrecoverable) onto a ServerClassifiedProviderError.","triggerScenarios":"`postMessages()` resolves but `response.ok` is false: 401/403 bad API key, 429 rate-limited, 400 invalid request/model name, 500/529 Anthropic outage — thrown at ClaudeObservationProvider.ts:82-89.","commonSituations":"Expired or wrong ANTHROPIC_API_KEY, hitting org rate limits during parallel generation, deprecated model ID sent to the API, Anthropic overloaded (529) during traffic spikes, billing issues.","solutions":["Read the classified error kind: retryable (429/5xx/529) → retry with the retryAfter delay; unrecoverable → fix the request or credentials.","Verify the API key and account billing/status in the Anthropic console.","Check the model identifier is valid and enabled for your account.","Respect the Retry-After header on 429/overloaded responses."],"exampleFix":"// before\nthrow new Error('claude failed');\n// after\nif (err.kind === 'retryable') return retryWithBackoff(call, err.retryAfterMs);\nlogger.error(`Anthropic unrecoverable: ${err.cause?.message}`);","handlingStrategy":"retry","validationCode":"if (!process.env.ANTHROPIC_API_KEY) throw new Error('ANTHROPIC_API_KEY not set');\n// and validate the model id against the account's allowed list before calling","typeGuard":"function isRetryableProviderError(e: unknown): boolean {\n  return typeof e === 'object' && e !== null && 'kind' in e && (e as {kind: string}).kind === 'retryable';\n}","tryCatchPattern":"try {\n  result = await provider.generate(prompt, signal);\n} catch (e) {\n  if (e.kind === 'retryable' && e.retryAfterMs) return sleep(e.retryAfterMs).then(call);\n  throw e;\n}","preventionTips":["Validate API key and billing status before deploying.","Throttle parallel generation to stay under org rate limits.","Pin and verify model IDs against current Anthropic model names.","Honor Retry-After headers; use exponential backoff with jitter."],"tags":["anthropic","http","api-error","rate-limit"],"backgroundTag":"api-error-response","analyzedSha":"d8bc9755e74915e5c3b999181e10a67c889bce2a","analyzedAt":"2026-09-17T16:40:26.182Z","contentChangedAt":"2026-09-17T16:40:26.182Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}