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
- Check network/DNS connectivity to api.anthropic.com from the runtime environment.
- Verify the base URL / proxy configuration for the Claude client.
- Retry with backoff if the cause is transient (timeout, connection reset).
- 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
- Check egress/network access to api.anthropic.com in every deployment environment.
- Use AbortSignals with sensible timeouts and distinguish abort from network failure.
- Always inspect the classified error's `kind` before deciding to retry.
- Log the wrapped `cause` — the raw socket/TLS error names the real problem.
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
- classifyHttpProviderError
- classifyGeminiError( )
- classifyGeminiServerError
- classifyOpenRouterError
- [claude-mem] Worker GET
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)