thedotmack/claude-mem · error · ServerClassifiedProviderError

classifyGeminiServerError

Error message

classifyGeminiServerError({ cause: err })

What it means

GeminiObservationProvider.generate wraps its call to the Gemini generateContent endpoint; a rejected postGenerateContent (no HTTP response at all) is rethrown via classifyGeminiServerError with only a cause. It indicates a transport-level failure — DNS, connection, TLS, timeout, or abort — before Google's API could answer.

Solutions

  1. Verify connectivity to generativelanguage.googleapis.com (curl/ping).
  2. Check proxy/firewall/egress rules in the runtime environment.
  3. Increase client timeout if long prompts cause timeouts; pass a longer AbortSignal.
  4. Retry with backoff for transient causes (reset, timeout).

Example fix

// before
const r = await geminiProvider.generate(prompt, signal);
// after
try { const r = await geminiProvider.generate(prompt, signal); }
catch (e) { if (isTransientNetwork(e)) return retryWithBackoff(); 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 geminiProvider.generate(prompt, signal);
} catch (e) {
  if (e.kind === 'retryable') return retryWithBackoff(() => geminiProvider.generate(prompt, signal));
  throw e;
}

Prevention

When it happens

Trigger: `postGenerateContent()` rejects: network unreachable, DNS failure, connection reset, timeout, or AbortSignal fired — caught at GeminiObservationProvider.ts:164-171 and wrapped as classifyGeminiServerError({ cause: err }).

Common situations: Corporate firewall blocking generativelanguage.googleapis.com, no internet in the container, GEMINI base URL/proxy misconfiguration, request timeout for very long prompts.

Related errors


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

Appendix: source

Thrown at src/server/generation/providers/GeminiObservationProvider.ts:168

    signal?: AbortSignal,
  ): Promise<ServerGenerationResult> {
    const { prompt, skippedAll } = buildServerGenerationPrompt(context);
    if (skippedAll) {
      return {
        rawText: '<skip_summary reason="all_events_private" />',
        providerLabel: this.providerLabel,
        modelId: this.model,
      };
    }

    const url = `${GEMINI_API_URL}/${encodeURIComponent(this.model)}:generateContent?key=${encodeURIComponent(this.apiKey)}`;

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

    if (!response.ok) {
      const bodyText = await safeReadBody(response);
      throw classifyGeminiServerError({
        status: response.status,
        bodyText,
        headers: response.headers,
        cause: new Error(`Gemini HTTP error (status ${response.status})`),
      });
    }

    let data: GeminiResponse;
    try {
      data = (await response.json()) as GeminiResponse;
    } catch (parseError) {

View on GitHub (pinned to d8bc9755e7)