thedotmack/claude-mem · error · ServerClassifiedProviderError

Anthropic API error

Error message

Anthropic API error: ${data.error.type} - ${data.error.message}

What it means

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.

Solutions

  1. Inspect data.error.type in the cause message to decide retry (overloaded_error) vs fix (invalid_request_error, authentication_error).
  2. Retry with backoff only for overloaded_error / rate-limit types.
  3. Validate the request payload (model, max_tokens, prompt format) if the type is invalid_request_error.
  4. Re-check the API key if the type is authentication_error or permission_error.

Example fix

// before
text = data.content[0].text;
// after
if (data.error) throw new Error(`API error envelope: ${data.error.type} - ${data.error.message}`);
text = data.content?.[0]?.text;
Defensive patterns

Strategy: type-guard

Type guard

function hasErrorEnvelope<T extends { error?: { type?: string; message?: string } }>(data: T): boolean {
  return data.error != null;
}

Try / catch

try {
  result = await provider.generate(prompt, signal);
} catch (e) {
  if (/overloaded_error/.test(String(e.cause?.message))) return retryWithBackoff();
  throw e;
}

Prevention

When it happens

Trigger: Response JSON parses successfully but `data.error` is present (overloaded_error, invalid_request_error, authentication_error, permission_error), thrown at ClaudeObservationProvider.ts:102-109.

Common situations: 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.

Related errors


AI-assisted analysis of thedotmack/claude-mem@d8bc9755e7 (2026-09-17). Data as JSON: /api/errors/a2c8db0d584e5697. Report an issue: GitHub.

Appendix: source

Thrown at src/server/generation/providers/ClaudeObservationProvider.ts:105

        bodyText,
        headers: response.headers,
        cause: new Error(`Anthropic API error: ${response.status} - ${bodyText}`),
      });
    }

    let data: AnthropicMessagesResponse;
    try {
      data = (await response.json()) as AnthropicMessagesResponse;
    } catch (parseError) {
      const err = parseError instanceof Error ? parseError : new Error(String(parseError));
      throw new ServerClassifiedProviderError('Anthropic returned invalid JSON', {
        kind: 'parse_error',
        cause: err,
      });
    }

    if (data.error) {
      throw classifyClaudeServerError({
        status: response.status,
        bodyText: `${data.error.type ?? ''} ${data.error.message ?? ''}`,
        headers: response.headers,
        cause: new Error(`Anthropic API error: ${data.error.type} - ${data.error.message}`),
      });
    }

    const blocks = Array.isArray(data.content) ? data.content : [];
    const rawText = blocks
      .filter(block => block?.type === 'text' && typeof block.text === 'string')
      .map(block => block.text!)
      .join('\n')
      .trim();

    if (!rawText) {
      logger.warn('SDK', 'Anthropic returned empty content array', {
        provider: 'claude',
        model: this.model,

View on GitHub (pinned to d8bc9755e7)