{"record":{"id":"a2c8db0d584e5697","repo":"thedotmack/claude-mem","slug":"anthropic-api-error-data-error-type-data-error-message","errorCode":null,"errorMessage":"Anthropic API error: ${data.error.type} - ${data.error.message}","messagePattern":"Anthropic API error: (.+?) - (.+?)","errorType":"exception","errorClass":"ServerClassifiedProviderError","httpStatus":null,"severity":"error","filePath":"src/server/generation/providers/ClaudeObservationProvider.ts","lineNumber":105,"sourceCode":"        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\n    if (data.error) {\n      throw classifyClaudeServerError({\n        status: response.status,\n        bodyText: `${data.error.type ?? ''} ${data.error.message ?? ''}`,\n        headers: response.headers,\n        cause: new Error(`Anthropic API error: ${data.error.type} - ${data.error.message}`),\n      });\n    }\n\n    const blocks = Array.isArray(data.content) ? data.content : [];\n    const rawText = blocks\n      .filter(block => block?.type === 'text' && typeof block.text === 'string')\n      .map(block => block.text!)\n      .join('\\n')\n      .trim();\n\n    if (!rawText) {\n      logger.warn('SDK', 'Anthropic returned empty content array', {\n        provider: 'claude',\n        model: this.model,","sourceCodeStart":87,"sourceCodeEnd":123,"githubUrl":"https://github.com/thedotmack/claude-mem/blob/d8bc9755e74915e5c3b999181e10a67c889bce2a/src/server/generation/providers/ClaudeObservationProvider.ts#L87-L123","documentation":"The Anthropic API returned a 200-style response whose parsed JSON contains an `error` object, so the provider throws it through classifyClaudeServerError with cause `Anthropic API error: <type> - <message>`. This happens when the HTTP layer reported success but the payload is an API error envelope (e.g. invalid_request_error). The classification uses the error type text plus the response status.","triggerScenarios":"Response JSON parses successfully but `data.error` is present (overloaded_error, invalid_request_error, authentication_error, permission_error), thrown at ClaudeObservationProvider.ts:102-109.","commonSituations":"Streaming/gateway proxies that return 200 with an error body, intermittent overloaded_error envelopes, account-level permission errors after key rotation, region restrictions on the API.","solutions":["Inspect data.error.type in the cause message to decide retry (overloaded_error) vs fix (invalid_request_error, authentication_error).","Retry with backoff only for overloaded_error / rate-limit types.","Validate the request payload (model, max_tokens, prompt format) if the type is invalid_request_error.","Re-check the API key if the type is authentication_error or permission_error."],"exampleFix":"// before\ntext = data.content[0].text;\n// after\nif (data.error) throw new Error(`API error envelope: ${data.error.type} - ${data.error.message}`);\ntext = data.content?.[0]?.text;","handlingStrategy":"type-guard","validationCode":null,"typeGuard":"function hasErrorEnvelope<T extends { error?: { type?: string; message?: string } }>(data: T): boolean {\n  return data.error != null;\n}","tryCatchPattern":"try {\n  result = await provider.generate(prompt, signal);\n} catch (e) {\n  if (/overloaded_error/.test(String(e.cause?.message))) return retryWithBackoff();\n  throw e;\n}","preventionTips":["Never assume a 200 response means success — check data.error before reading data.content.","Retry only overloaded_error types; treat invalid_request/authentication as fatal.","Validate request payloads (model, max_tokens) to avoid invalid_request_error.","Monitor Anthropic status pages for overloaded periods."],"tags":["anthropic","api-error","json","error-envelope"],"backgroundTag":"upstream-api-error","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"}