thedotmack/claude-mem · error · ServerClassifiedProviderError

classifyClaudeServerError

Error message

classifyClaudeServerError({ cause: err })

What it means

ClaudeObservationProvider.generate wraps the network call to the Anthropic messages API; any exception from postMessages (fetch rejection) is wrapped via classifyClaudeServerError with only a cause and no HTTP status. This signals a transport-level failure — the request never got an HTTP response. The classified error carries kind information (e.g. retryable vs unrecoverable) derived from the cause.

Solutions

  1. Check network/DNS connectivity to api.anthropic.com from the runtime environment.
  2. Verify the base URL / proxy configuration for the Claude client.
  3. Retry with backoff if the cause is transient (timeout, connection reset).
  4. Inspect the wrapped cause error for the underlying socket/TLS message.

Example fix

// before
const res = await provider.generate(prompt, signal);
// after
try { const res = await provider.generate(prompt, signal); }
catch (e) { if (e.kind === 'retryable') await sleep(backoff); else throw e; }
Defensive patterns

Strategy: try-catch

Type guard

function isNetworkError(e: unknown): e is TypeError {
  return e instanceof TypeError && /fetch|network/i.test(e.message);
}

Try / catch

try {
  result = await provider.generate(prompt, signal);
} catch (e) {
  if (e.kind === 'retryable') return retryWithBackoff(() => provider.generate(prompt, signal));
  throw e;
}

Prevention

When it happens

Trigger: `postMessages()` rejects: DNS failure, connection refused/reset, TLS error, request timeout, or AbortSignal firing — caught in the try/catch at ClaudeObservationProvider.ts:74-80 and rethrown as classifyClaudeServerError({ cause: err }).

Common situations: Missing/blocked network in CI containers, proxy or VPN drops, DNS misconfiguration, ANTHROPIC_BASE_URL pointing at an unreachable host, transient outage of api.anthropic.com.

Related errors


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

Appendix: source

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

    signal?: AbortSignal,
  ): Promise<ServerGenerationResult> {
    const { prompt, skippedAll } = buildServerGenerationPrompt(context);
    if (skippedAll) {
      // All events were scrubbed by privacy stripping. Don't bill the
      // provider — return a synthetic skip response that parser accepts.
      return {
        rawText: '<skip_summary reason="all_events_private" />',
        providerLabel: this.providerLabel,
        modelId: this.model,
      };
    }

    let response: Response;
    try {
      response = await this.postMessages(prompt, signal);
    } catch (networkError) {
      const err = networkError instanceof Error ? networkError : new Error(String(networkError));
      throw classifyClaudeServerError({
        cause: err,
      });
    }

    if (!response.ok) {
      const bodyText = await safeReadBody(response);
      throw classifyClaudeServerError({
        status: response.status,
        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) {

View on GitHub (pinned to d8bc9755e7)