thedotmack/claude-mem · error
classifyGeminiError( )
Error message
classifyGeminiError({ cause: err }) What it means
In GeminiProvider.queryGeminiMultiTurn, any failure thrown by fetchGenerateContent — DNS resolution errors, connection resets, TLS failures, timeouts, or AbortSignal aborts — is wrapped via classifyGeminiError into a structured error object before propagating to the caller. classifyGeminiError inspects the cause and attaches a classification (e.g. network vs abort vs rate limit) used for retry and user-facing messaging.
Solutions
- Catch the classified error in the caller and check its classification before retrying
- Retry network-classified failures with backoff; respect any retry-after data attached by the classifier
- Check connectivity/proxy settings (HTTPS_PROXY) for persistent connection failures
- Distinguish abort errors (user intent) from network errors and do not auto-retry aborts
Example fix
// before
const text = await provider.query(messages);
// after
try {
const text = await provider.query(messages);
} catch (e) {
if ((e as GeminiError).classification === 'network') await backoffRetry(() => provider.query(messages));
else throw e;
} Defensive patterns
Strategy: retry
Validate before calling
// Before calling, verify connectivity and endpoint reachability
if (typeof navigator !== 'undefined' && navigator.onLine === false) {
throw new Error('offline: skip Gemini query until network returns');
} Type guard
const isNetworkClassified = (e: unknown): e is { classification: 'network'; cause: Error } =>
typeof e === 'object' && e !== null && (e as any).classification === 'network'; Try / catch
try {
const text = await provider.query(messages);
} catch (e) {
if (isNetworkClassified(e) && !isAbortError(e.cause)) {
return backoffRetry(() => provider.query(messages), { retries: 3 });
}
throw e;
} Prevention
- Retry with exponential backoff for network-classified failures
- Never retry AbortError — that is user intent
- Check HTTPS_PROXY / VPN / firewall rules for generativelanguage.googleapis.com
- Wrap long multi-turn sessions with a watchdog that reconnects on transient failures
When it happens
Trigger: The fetch to the Gemini generateContent endpoint fails before an HTTP response exists: network outage, DNS failure, connection refused/reset, request aborted via attemptSignal, or fetch throwing for a malformed URL/proxy issue.
Common situations: Offline or flaky network during a long multi-turn session; corporate proxy blocking generativelanguage.googleapis.com; user cancellation propagating an abort; VPN drops mid-request.
Related errors
- classifyClaudeServerError
- classifyGeminiServerError
- classifyHttpProviderError
- classifyOpenRouterError
- [claude-mem] Worker GET
AI-assisted analysis of thedotmack/claude-mem@d8bc9755e7 (2026-09-17).
Data as JSON: /api/errors/0e5b0ed0d34c6b0e.
Report an issue: GitHub.
Appendix: source
Thrown at src/services/worker/GeminiProvider.ts:351
turns: history.length,
totalChars
});
const url = `${GEMINI_API_URL}/${model}:generateContent?key=${apiKey}`;
await enforceRateLimitForModel(model, rateLimitingEnabled);
// Track request-id (best-effort dedup) across retries.
let priorRequestId: string | null = null;
const data = await withRetry<GeminiResponse>(async (attemptSignal) => {
let response: Response;
try {
response = await this.fetchGenerateContent(url, contents, priorRequestId, attemptSignal);
} catch (networkError: unknown) {
// Network failures, aborts, DNS, etc.
const err = networkError instanceof Error ? networkError : new Error(String(networkError));
throw classifyGeminiError({
cause: err,
});
}
const requestId = response.headers.get('x-goog-request-id') ?? response.headers.get('x-request-id');
if (requestId) {
priorRequestId = requestId;
} else {
logger.debug('SDK', 'Gemini response missing request-id header; retry dedup is best-effort');
}
if (!response.ok) {
const errorBody = await response.text();
throw classifyGeminiError({
status: response.status,
bodyText: errorBody,
headers: response.headers,
cause: new Error(`Gemini API error (status ${response.status})`),View on GitHub (pinned to d8bc9755e7)