thedotmack/claude-mem · error
classifyOpenRouterError
Error message
classifyOpenRouterError({ cause: err }) What it means
In OpenRouterProvider.queryOpenRouterMultiTurn, errors thrown by fetchChatCompletion — network failures, DNS errors, connection resets, timeouts, aborts — are passed through classifyOpenRouterError, which wraps the cause into a structured, classified error object before it propagates. This mirrors the Gemini provider pattern and enables consistent retry/messaging logic for OpenRouter requests.
Solutions
- Catch the classified error and branch on its classification before deciding to retry
- Auto-retry network-classified errors with exponential backoff; never retry user aborts
- Check connectivity and proxy/firewall rules for openrouter.ai on persistent failures
- Surface the wrapped cause's message for diagnosis when classification is unknown
Example fix
// before
const res = await provider.query(messages);
// after
try {
const res = await provider.query(messages);
} catch (e) {
if ((e as OpenRouterError).classification === 'network' && !isAbort(e)) await backoffRetry();
throw e;
} Defensive patterns
Strategy: retry
Validate before calling
// Reachability pre-check for OpenRouter
const ok = await fetch('https://openrouter.ai/api/v1/models', { method: 'HEAD' })
.then(() => true).catch(() => false);
if (!ok) throw new Error('openrouter.ai unreachable — check network/proxy'); Type guard
const isOpenRouterNetworkError = (e: unknown): e is { classification: 'network'; cause: Error } =>
typeof e === 'object' && e !== null && (e as any).classification === 'network'; Try / catch
try {
const res = await provider.query(messages);
} catch (e) {
if (isOpenRouterNetworkError(e) && e.cause.name !== 'AbortError') {
return backoffRetry(() => provider.query(messages), { retries: 3 });
}
throw e;
} Prevention
- Retry network-classified errors with exponential backoff
- Distinguish aborts from network failures and never retry aborts
- Verify proxy/firewall allows openrouter.ai for CI and corporate environments
- Set a sane client timeout above expected completion latency to avoid self-inflicted timeouts
When it happens
Trigger: The fetch to OpenRouter's /chat/completions endpoint fails before receiving an HTTP response: network outage, DNS failure, connection refused, TLS error, or the attemptSignal aborted the request.
Common situations: Flaky network or VPN drop mid-request; firewall or proxy blocking openrouter.ai; request aborted by user cancellation; long completions exceeding a client-side timeout.
Related errors
- classifyHttpProviderError
- classifyClaudeServerError
- classifyGeminiError( )
- [claude-mem] Worker GET
- [claude-mem] Worker POST
AI-assisted analysis of thedotmack/claude-mem@d8bc9755e7 (2026-09-17).
Data as JSON: /api/errors/d786b4cc25b0e48f.
Report an issue: GitHub.
Appendix: source
Thrown at src/services/worker/OpenRouterProvider.ts:542
const messages = this.conversationToOpenAIMessages(history);
const totalChars = history.reduce((sum, m) => sum + m.content.length, 0);
const estimatedTokens = this.estimateTokens(messages.map(m => m.content).join(''));
logger.debug('SDK', `Querying OpenRouter multi-turn (${model})`, {
turns: history.length,
totalChars,
estimatedTokens
});
let priorRequestId: string | null = null;
const data = await withRetry<OpenRouterResponse>(async (attemptSignal) => {
let response: Response;
try {
response = await this.fetchChatCompletion(apiUrl, apiKey, model, fallbackModels, messages, siteUrl, appName, priorRequestId, attemptSignal, plainText);
} catch (networkError: unknown) {
const err = networkError instanceof Error ? networkError : new Error(String(networkError));
throw classifyOpenRouterError({ cause: err });
}
const requestId = response.headers.get('x-request-id') ?? response.headers.get('x-openrouter-request-id');
if (requestId) {
priorRequestId = requestId;
} else {
logger.debug('SDK', 'OpenRouter response missing request-id header; retry dedup is best-effort');
}
if (!response.ok) {
const errorText = await response.text();
throw classifyOpenRouterError({
status: response.status,
bodyText: errorText,
headers: response.headers,
cause: new Error(`OpenRouter API error: ${response.status} - ${errorText}`),
...(requestId ? { requestId } : {}),
});View on GitHub (pinned to d8bc9755e7)