{"record":{"id":"44ab19c933c4720e","repo":"invoke-ai/InvokeAI","slug":"gemini-request-failed-with-status-response-status","errorCode":null,"errorMessage":"Gemini request failed with status {response.status_code} for model '{model_id}': {response.text}","messagePattern":"Gemini request failed with status (.+?) for model '(.+?)': (.+?)","errorType":"exception","errorClass":"ExternalProviderRequestError","httpStatus":null,"severity":"error","filePath":"invokeai/app/services/external_generation/providers/gemini.py","lineNumber":120,"sourceCode":"        }\n        if \"thinking_level\" in opts:\n            payload[\"thinkingConfig\"] = {\"thinkingLevel\": opts[\"thinking_level\"].upper()}\n\n        response = requests.post(\n            endpoint,\n            params={\"key\": api_key},\n            json=payload,\n            timeout=120,\n        )\n\n        if not response.ok:\n            if response.status_code == 429:\n                retry_after = _parse_retry_after(response.headers.get(\"retry-after\"))\n                raise ExternalProviderRateLimitError(\n                    f\"Gemini rate limit exceeded. {f'Retry after {retry_after:.0f}s.' if retry_after else 'Please try again later.'}\",\n                    retry_after=retry_after,\n                )\n            raise ExternalProviderRequestError(\n                f\"Gemini request failed with status {response.status_code} for model '{model_id}': {response.text}\"\n            )\n\n        data = response.json()\n        if not isinstance(data, dict):\n            raise ExternalProviderRequestError(\"Gemini response payload was not a JSON object\")\n        images: list[ExternalGeneratedImage] = []\n        text_parts: list[str] = []\n        finish_messages: list[str] = []\n        candidates = data.get(\"candidates\")\n        if not isinstance(candidates, list):\n            raise ExternalProviderRequestError(\"Gemini response payload missing candidates\")\n        for candidate in candidates:\n            if not isinstance(candidate, dict):\n                continue\n            finish_message = candidate.get(\"finishMessage\")\n            finish_reason = candidate.get(\"finishReason\")\n            if isinstance(finish_message, str):","sourceCodeStart":102,"sourceCodeEnd":138,"githubUrl":"https://github.com/invoke-ai/InvokeAI/blob/0b6a024f2ff6a86bfb953dcdb9cc504ef7397a06/invokeai/app/services/external_generation/providers/gemini.py#L102-L138","documentation":"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.","triggerScenarios":"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).","commonSituations":"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.","solutions":["Read the response.text portion of the message — Google's JSON error body names the exact problem (API_KEY_INVALID, NOT_FOUND, etc.).","If 401/403: verify/replace the Gemini API key and confirm the Generative Language API is enabled for the project.","If 404: check request.model.provider_model_id matches a valid Gemini model (the provider strips a 'models/' prefix, extra path segments are not).","If 400: simplify the request (drop provider_options like thinking_level/imageConfig, use supported aspect ratios/sizes).","If 5xx: retry later; check the Google Cloud status dashboard."],"exampleFix":"// before: opaque failure\nraise RuntimeError(\"generation failed\")\n// after: log full status/body surfaced by the provider\ntry:\n    result = provider.generate(request)\nexcept ExternalProviderRequestError as e:\n    logger.error(\"Gemini request failed: %s\", e)  # includes status + response text\n    raise","handlingStrategy":"try-catch","validationCode":"// pre-flight: verify key + model are accepted\nprobe = requests.get(\n    f\"https://generativelanguage.googleapis.com/v1beta/models/{model_id}\",\n    params={\"key\": api_key}, timeout=10,\n)\nif probe.status_code != 200:\n    raise RuntimeError(f\"Gemini preflight failed: {probe.status_code} {probe.text}\")","typeGuard":null,"tryCatchPattern":"try:\n    result = provider.generate(request)\nexcept ExternalProviderRequestError as e:\n    msg = str(e)\n    if \"401\" in msg or \"403\" in msg:\n        alert_bad_credentials(\"gemini\")\n    elif \"404\" in msg:\n        alert_bad_model(request.model.provider_model_id)\n    else:\n        logger.error(\"Gemini HTTP failure: %s\", msg)\n        raise","preventionTips":["Validate the API key and model id with a cheap GET /models call before paid generations.","Pin supported model ids in configuration; don't accept arbitrary user input.","Keep provider options (thinking_level, imageConfig) within documented model capabilities.","Subscribe to Google Cloud status updates to anticipate 5xx incidents."],"tags":["http-error","gemini","api-key","external-api","authentication"],"backgroundTag":"http-error-response","analyzedSha":"0b6a024f2ff6a86bfb953dcdb9cc504ef7397a06","analyzedAt":"2026-08-29T04:46:49.967Z","schemaVersion":2},"datasetVersion":"2026-08-29T07:17:48.351Z"}