invoke-ai/InvokeAI · error · ExternalProviderRequestError

Gemini request failed with status {response.status_code} for

Error message

Gemini request failed with status {response.status_code} for model '{model_id}': {response.text}

What it means

ExternalProviderRequestError raised when the Gemini API returns a non-OK HTTP status other than 429 (429 has its own rate-limit branch). The message embeds the HTTP status code, the requested model id, and the raw response body text so the developer can see Google's error payload. It is a catch-all for authentication failures, bad requests, invalid model names, permission errors, and server errors.

Source

Thrown at invokeai/app/services/external_generation/providers/gemini.py:120

        }
        if "thinking_level" in opts:
            payload["thinkingConfig"] = {"thinkingLevel": opts["thinking_level"].upper()}

        response = requests.post(
            endpoint,
            params={"key": api_key},
            json=payload,
            timeout=120,
        )

        if not response.ok:
            if response.status_code == 429:
                retry_after = _parse_retry_after(response.headers.get("retry-after"))
                raise ExternalProviderRateLimitError(
                    f"Gemini rate limit exceeded. {f'Retry after {retry_after:.0f}s.' if retry_after else 'Please try again later.'}",
                    retry_after=retry_after,
                )
            raise ExternalProviderRequestError(
                f"Gemini request failed with status {response.status_code} for model '{model_id}': {response.text}"
            )

        data = response.json()
        if not isinstance(data, dict):
            raise ExternalProviderRequestError("Gemini response payload was not a JSON object")
        images: list[ExternalGeneratedImage] = []
        text_parts: list[str] = []
        finish_messages: list[str] = []
        candidates = data.get("candidates")
        if not isinstance(candidates, list):
            raise ExternalProviderRequestError("Gemini response payload missing candidates")
        for candidate in candidates:
            if not isinstance(candidate, dict):
                continue
            finish_message = candidate.get("finishMessage")
            finish_reason = candidate.get("finishReason")
            if isinstance(finish_message, str):

View on GitHub (pinned to 0b6a024f2f)

Solutions

  1. Read the response.text portion of the message — Google's JSON error body names the exact problem (API_KEY_INVALID, NOT_FOUND, etc.).
  2. If 401/403: verify/replace the Gemini API key and confirm the Generative Language API is enabled for the project.
  3. If 404: check request.model.provider_model_id matches a valid Gemini model (the provider strips a 'models/' prefix, extra path segments are not).
  4. If 400: simplify the request (drop provider_options like thinking_level/imageConfig, use supported aspect ratios/sizes).
  5. If 5xx: retry later; check the Google Cloud status dashboard.

Example fix

// before: opaque failure
raise RuntimeError("generation failed")
// after: log full status/body surfaced by the provider
try:
    result = provider.generate(request)
except ExternalProviderRequestError as e:
    logger.error("Gemini request failed: %s", e)  # includes status + response text
    raise
Defensive patterns

Strategy: try-catch

Validate before calling

// pre-flight: verify key + model are accepted
probe = requests.get(
    f"https://generativelanguage.googleapis.com/v1beta/models/{model_id}",
    params={"key": api_key}, timeout=10,
)
if probe.status_code != 200:
    raise RuntimeError(f"Gemini preflight failed: {probe.status_code} {probe.text}")

Try / catch

try:
    result = provider.generate(request)
except ExternalProviderRequestError as e:
    msg = str(e)
    if "401" in msg or "403" in msg:
        alert_bad_credentials("gemini")
    elif "404" in msg:
        alert_bad_model(request.model.provider_model_id)
    else:
        logger.error("Gemini HTTP failure: %s", msg)
        raise

Prevention

When it happens

Trigger: requests.post to {base_url}/models/{model_id}:generateContent returns response.ok == False with status_code != 429 — e.g. 400 (malformed payload/unsupported imageConfig), 401/403 (invalid or restricted API key), 404 (unknown model id), 500/503 (Google server error).

Common situations: Wrong or revoked API key; calling a model id that doesn't exist or isn't enabled for the key; custom external_gemini_base_url missing the /v1beta suffix handling expectations; unsupported width/height combination producing an invalid generationConfig; Gemini service incident.

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 invoke-ai/InvokeAI@0b6a024f2f (2026-08-29). Data as JSON: /api/errors/44ab19c933c4720e. Report an issue: GitHub.