◉GEMINI LABJP
●ARGON — gemini-4-argon is generally available as of 10/13, aimed at complex coding, agents, math and science●DEEP RES — deep-research-pro-preview-12-2025 shuts down 10/23, 6 days left. Move to deep-research-preview-04-2026●NANO — gemini-nano-banana-2.1 is GA (10/06). gemini-3.1-flash-image is deprecated with no shutdown date yet●MCP — One write-up cut an 85,000-token tool result to 310 tokens by wrapping it in an ADK FunctionTool●FLASH — gemini-3.7-flash and 3.5-flash now route automatically to newer Flash models (10/08)●NEW — Stop Re-Reading Every Crash Report: Gre…●ARGON — gemini-4-argon is generally available as of 10/13, aimed at complex coding, agents, math and science●DEEP RES — deep-research-pro-preview-12-2025 shuts down 10/23, 6 days left. Move to deep-research-preview-04-2026●NANO — gemini-nano-banana-2.1 is GA (10/06). gemini-3.1-flash-image is deprecated with no shutdown date yet●MCP — One write-up cut an 85,000-token tool result to 310 tokens by wrapping it in an ADK FunctionTool●FLASH — gemini-3.7-flash and 3.5-flash now route automatically to newer Flash models (10/08)●NEW — Stop Re-Reading Every Crash Report: Gre…
Articles/API / SDK
◈ API / SDK/2026-04-09Intermediate

Classify Gemini API Errors by Status — Handling 429, SAFETY, and Token Limits in Production

Sort Gemini API failures along two axes — HTTP status and finish_reason — so you know instantly whether to wait or to fix. Covers the three distinct 429 limits, model-deprecation fallbacks, and how the exception hierarchy changes after moving to the google-genai SDK.

gemini-api286troubleshooting87error15rate-limit4

✦ Premium Article

On the first day I wired the Gemini API into one of my indie apps, what cost me the most time wasn't the error codes themselves — it was deciding whether a given failure would clear up if I waited, or whether I had to go fix my code. A 429 tells you something is wrong, but not whether it's a rate limit or an auth problem until you read the status in the response.

This walkthrough organizes the errors you'll hit by their status and finish_reason, then turns them into handling that won't stall in production — with the code I actually use. The goal isn't a list of errors; it's being able to act without hesitation the moment one shows up.

The First Ninety Seconds

When something fails, the first thing I add isn't a fix — it's a single line of output. Look at the exception type and the code carried in the response before anything else. Skip that and start with "just retry it," and you end up with code that patiently waits on failures that will never clear.

except Exception as e:
    # Print the type and code first. Everything else branches from here.
    print(type(e).__name__, getattr(e, "code", None), getattr(e, "message", e))

There are only two axes worth looking at.

  • HTTP status (400 / 401 / 403 / 429 / 500-503) — whether the request was accepted at all
  • finish_reason (SAFETY / RECITATION / MAX_TOKENS) — whether an accepted request stopped mid-generation

The first is a problem with how you're sending; the second is a problem with what you're sending. Users report both as "nothing came back," but the fixes have nothing in common. The rest of this walkthrough follows those two axes, status family by status family.

400 Bad Request — Invalid Requests and Wrong Model Names

A 400 error means the API can't understand your request. The three most common causes are model name mistakes, malformed JSON, and input that's too long.

1. Using the wrong model name

Typos or outdated model names are the number-one cause of 400 errors. The Gemini API only accepts specific model names.

import google.generativeai as genai
 
genai.configure(api_key="YOUR_GEMINI_API_KEY")
 
# ❌ Wrong: Model doesn't exist
model = genai.GenerativeModel("gemini-invalid-model")
 
# ✅ Correct: Use a real model name
model = genai.GenerativeModel("gemini-2.5-flash")
response = model.generate_content("Hello, world!")
print(response.text)

You can find the latest available models on the Google AI Studio model selection page. Here are the most commonly used ones:

  • gemini-2.5-flash — Fast and inexpensive; fine for everything you do while iterating
  • gemini-2.5-pro — Higher quality, for long summaries and harder reasoning
  • gemini-3-pro — Latest generation; availability varies by region

2. Malformed JSON in your request

When using TypeScript or JavaScript, if your request body's JSON structure isn't correct, you'll get a 400 error. Make sure all required fields are present.

import { GoogleGenerativeAI } from "@google/generative-ai";
 
const genAI = new GoogleGenerativeAI("YOUR_GEMINI_API_KEY");
const model = genAI.getGenerativeModel({ model: "gemini-2.5-flash" });
 
// ✅ Correct request structure
const response = await model.generateContent({
  contents: [
    {
      role: "user",
      parts: [{ text: "Hello, world!" }],
    },
  ],
});

Pay special attention to required fields like contents, parts, and role. Missing any of these will cause a 400 error.

3. Input text exceeds maximum length

Very long text inputs can trigger a 400 error. Each Gemini model has a context window limit (the maximum amount of text you can send):

  • gemini-2.5-flash — Up to 1 million tokens

If you need to process large amounts of text, split it into smaller chunks and make multiple requests.

✦

Thank you for reading this far.

Continue Reading

What follows includes implementation code, benchmarks, and practical content we hope you'll find useful. This site runs without ads — server and development costs are supported entirely by members like you. If it's been helpful, we'd be truly grateful for your support.

WHAT YOU'LL LEARN
✦A single error handler that classifies exceptions by status and finish_reason to decide retry vs. fail
✦Splitting 429s across RPM, RPD, and TPM, with jittered exponential backoff to avoid retry storms
✦Turning empty responses, SAFETY, RECITATION, and context overflow into cause-specific fixes
Secure payment via Stripe · Cancel anytime
✦

Unlock This Article

Get full access to the rest of this article. Buy once, read anytime. This site is ad-free — your support goes directly toward keeping it running.

or
Unlock all articles with Membership →
Share

Thank You for Reading

Gemini Lab is ad-free, supported entirely by members like you. We publish practical guides daily with implementation code, benchmarks, and production-ready patterns. If you've found it useful, we'd love to have you on board.

  • ✦Copy-paste ready implementation code
  • ✦New advanced guides published daily
  • ✦$5/mo or $10 for lifetime access
View Membership →

Related Articles

◈ API / SDK2026-10-16
The Day /models Returns 200 but generateContent Returns 403 — Decide Your Triage Order Before It Happens
A triage order for the case where listing models succeeds with 200 but generation fails with 403 permission_denied. Includes a small diagnostic script that checks key, project, and billing in turn, why you should not retry a 403, and how to assemble what support needs.
◈ API / SDK2026-05-20
Gemini API Streaming Works Locally but Buffers in Production — Fixing Cloud Run, Vercel, and Cloudflare
Streaming responses flow token-by-token in local dev, then arrive as one big blob in production. A walkthrough of the five most common causes — Cloud Run timeouts, Vercel runtime mismatch, Cloudflare Workers proxying, server-side text() pitfalls, and client-side decoding — with the fixes I use on my own sites.
◈ API / SDK2026-05-17
Diagnosing INVALID_ARGUMENT Errors in Gemini API Batch Image Analysis
When using the Gemini API to analyze multiple images at once, INVALID_ARGUMENT errors can be surprisingly hard to diagnose. This guide covers the three root causes—MIME type mismatches, inline data size limits, and contents structure errors—with code to fix each one.