Seeing 429 RESOURCE_EXHAUSTED from the Gemini API? Check these in order:
- Are you on the free tier? Free limits are tight and include a per-day (RPD) cap — enabling billing raises all of them dramatically.
- Which quota did you hit — per minute or per day? A per-day cap won’t clear by waiting a few seconds; it resets at midnight Pacific.
- Add backoff + jitter for the per-minute case, and consider a smaller/faster model (e.g. Flash) with higher headroom.
Google Gemini returns HTTP 429 with status RESOURCE_EXHAUSTED when you exceed a quota. The twist that catches developers out: Gemini enforces requests per minute (RPM), tokens per minute (TPM), and requests per day (RPD). Backoff handles the per-minute limits, but a per-day cap is a different beast — it won’t clear no matter how long you retry within the day.
What this error means
{
"error": {
"code": 429,
"message": "Resource has been exhausted (e.g. check quota).",
"status": "RESOURCE_EXHAUSTED"
}
} There are three quota dimensions, and any one of them returns the same 429:
| Quota | Window | Clears by waiting? |
|---|---|---|
| RPM — requests per minute | Rolling minute | Yes — seconds |
| TPM — tokens per minute | Rolling minute | Yes — seconds |
| RPD — requests per day | Per calendar day (PT) | No — resets at midnight Pacific |
Common causes
- Free-tier limits. The free tier has low RPM and a hard daily request cap. Hobby projects hit the RPD ceiling and assume the API is broken.
- The per-day cap (RPD). You sail through the morning, then every request 429s by afternoon. Backoff won’t help — you’re out of daily quota.
- Bursty concurrency exceeding RPM in a single window.
- Large prompts burning TPM (long context, files, images).
- Per-model quotas. Limits are tracked per model; a heavily-used model can be exhausted while another has room.
How to fix it
Enable billing — the biggest single lever
Moving a project from the free tier to pay-as-you-go raises RPM/TPM/RPD by orders of magnitude. If you’re building anything beyond a toy, set up billing in Google AI Studio / Cloud Console first — it resolves most RESOURCE_EXHAUSTED errors outright.
Back off and retry (per-minute quotas)
from google import genai
from google.genai import errors
import time, random
client = genai.Client() # reads GEMINI_API_KEY from env
def generate_with_backoff(prompt, model="gemini-2.5-flash", max_attempts=6):
for attempt in range(max_attempts):
try:
return client.models.generate_content(model=model, contents=prompt)
except errors.APIError as e:
if e.code != 429 or attempt == max_attempts - 1:
raise
time.sleep((2 ** attempt) + random.random())
resp = generate_with_backoff("Hello")
print(resp.text) import { GoogleGenAI } from "@google/genai";
const ai = new GoogleGenAI({}); // reads GEMINI_API_KEY from env
const sleep = (ms) => new Promise((r) => setTimeout(r, ms));
async function generateWithBackoff(prompt, model = "gemini-2.5-flash", maxAttempts = 6) {
for (let attempt = 0; attempt < maxAttempts; attempt++) {
try {
return await ai.models.generateContent({ model, contents: prompt });
} catch (err) {
const status = err?.status ?? err?.code;
if (status !== 429 || attempt === maxAttempts - 1) throw err;
await sleep(2 ** attempt * 1000 + Math.random() * 1000);
}
}
}
const resp = await generateWithBackoff("Hello");
console.log(resp.text); curl "https://generativelanguage.googleapis.com/v1beta/models/gemini-2.5-flash:generateContent" \
--retry 5 --retry-all-errors --retry-max-time 60 \
-H "x-goog-api-key: $GEMINI_API_KEY" \
-H "Content-Type: application/json" \
-d '{"contents":[{"parts":[{"text":"Hello"}]}]}' If it’s the daily cap (RPD)
Backoff won’t save you — the quota resets at midnight Pacific. Your options:
- Enable billing to raise (or remove) the daily cap.
- Request a quota increase in the Cloud Console (IAM & Admin → Quotas) for the specific model/limit.
- Switch to a model with higher quota — Flash-class models generally have far more headroom than Pro.
- Spread work across the day if you must stay on free-tier limits.
Check your real quotas
Don’t guess your ceilings — view them in Google AI Studio (per API key) or the Cloud Console Quotas page, filtered to the Generative Language API and your model. See the rate limits reference for how provider tiers scale.
How to prevent it
- Run on a billed project for anything production — free-tier caps are for prototyping.
- Throttle batch work behind a limiter under your RPM/TPM.
- Route tolerant tasks to Flash to preserve Pro quota.
- Track usage against the daily cap and alert before you hit it, since it won’t self-heal mid-day.
Retrying a per-day (RPD) exhaustion in a tight loop just burns CPU and logs noise — the quota is gone until the daily reset. Detect a sustained 429 and stop, rather than hammering until midnight.
Related errors and providers
- The same class on other providers: OpenAI 429 rate limit and Anthropic 429 rate limit.
- Comparing options before committing? See the pricing comparisons.
If Gemini’s free-tier or daily caps keep blocking you, routing across providers buys headroom without rewriting SDK code. OpenRouter exposes Gemini and other models through one OpenAI-compatible API with failover. (Affiliate link.)
What to do next
- Determine whether you hit a per-minute or per-day quota — they need different fixes.
- Enable billing to lift free-tier ceilings, the highest-impact change.
- Add capped backoff with jitter for per-minute limits.
- Request a quota increase or switch to a Flash model if you’re still constrained.