thedotmack/claude-mem · error · ServerClassifiedProviderError

Gemini HTTP error (status )

Error message

Gemini HTTP error (status ${response.status})

What it means

The Gemini generateContent endpoint returned a non-2xx status. GeminiObservationProvider reads the body and calls classifyGeminiServerError with status/bodyText/headers and cause `Gemini HTTP error (status <status>)`. The Gemini classifier adds special handling: 400 without quota markers becomes 'unrecoverable' with a categorized bad-request message, and quota bodies map to rate-limit handling.

Solutions

  1. Check status: 429/quota → honor Retry-After and back off; 400 → fix model name and request payload (must use v1beta for Gemini 3.x models).
  2. Verify the GEMINI/GOOGLE API key and its region/permission settings.
  3. Reduce request rate or request a quota increase for the project.
  4. Inspect the bodyText in the cause for Google's exact error message.

Example fix

// before
url = 'https://generativelanguage.googleapis.com/v1/models/...';
// after
url = 'https://generativelanguage.googleapis.com/v1beta/models/...';
Defensive patterns

Strategy: retry

Validate before calling

if (!process.env.GEMINI_API_KEY) throw new Error('GEMINI_API_KEY not set');
if (!/v1beta/.test(baseUrl)) throw new Error('Gemini requires v1beta API version');

Type guard

function isRetryableProviderError(e: unknown): boolean {
  return typeof e === 'object' && e !== null && 'kind' in e && (e as {kind: string}).kind === 'retryable';
}

Try / catch

try {
  result = await geminiProvider.generate(prompt, signal);
} catch (e) {
  if (e.kind === 'retryable' && e.retryAfterMs) return sleep(e.retryAfterMs).then(call);
  throw e;
}

Prevention

When it happens

Trigger: `response.ok` is false after postGenerateContent: 400 invalid API version/model/payload, 403 key restricted, 429 quota exceeded, 5xx Google-side errors — thrown at GeminiObservationProvider.ts:172-179.

Common situations: Calling v1 instead of required v1beta API version, invalid or region-locked API key, exhausting free-tier requests-per-minute or per-day quota, sending unsupported payload fields.

Understand the failure class

Background: "API error: {status}" and "HTTP 401/403/404/429/5xx" errors: non-2xx HTTP responses explained — this error's family across 27 libraries.

Related errors


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

Appendix: source

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

        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) {
      const err = parseError instanceof Error ? parseError : new Error(String(parseError));
      throw new ServerClassifiedProviderError('Gemini returned invalid JSON', {
        kind: 'parse_error',
        cause: err,
      });
    }

View on GitHub (pinned to d8bc9755e7)