Blog

Gemini API "429 RESOURCE_EXHAUSTED": What It Means and How to Fix It

Short answer

A 429 with "status": "RESOURCE_EXHAUSTED" means your Google Cloud project went over one of its Gemini API limits: requests per minute (RPM), input tokens per minute (TPM), requests per day (RPD), or on paid tiers a spend-based limit. Google's rate limits page says exceeding any one of them triggers the error.

What to do depends on which limit you hit:

  • A per-minute limit: wait and retry with exponential backoff. The official SDKs already do this.
  • A daily quota: retrying won't help until it resets at midnight Pacific time. Move the project to a paid tier, use another model, or wait.
  • A spend-based limit (paid tiers): slow down expensive requests, or ask for a higher limit.

Limits apply per project, not per API key, so a new key in the same project hits the same wall. If you'd rather not set up Google billing, you can call Gemini through TeamoRouter with one pay-per-use key, from $5.

What the error looks like

This is the body of a per-day quota error, quoted in google-gemini/gemini-cli#9248 (September 2025, gemini-2.5-pro, free tier). It's shown unescaped, with the Help link detail left out:

text
{
  "error": {
    "code": 429,
    "message": "You exceeded your current quota, please check your plan and billing details. For more information on this error, head to: https://ai.google.dev/gemini-api/docs/rate-limits.\n* Quota exceeded for metric: generativelanguage.googleapis.com/generate_content_free_tier_requests, limit: 50\nPlease retry in 34.074824224s.",
    "status": "RESOURCE_EXHAUSTED",
    "details": [
      {
        "@type": "type.googleapis.com/google.rpc.QuotaFailure",
        "violations": [
          {
            "quotaMetric": "generativelanguage.googleapis.com/generate_content_free_tier_requests",
            "quotaId": "GenerateRequestsPerDayPerProjectPerModel-FreeTier",
            "quotaDimensions": { "location": "global", "model": "gemini-2.5-pro" },
            "quotaValue": "50"
          }
        ]
      },
      {
        "@type": "type.googleapis.com/google.rpc.RetryInfo",
        "retryDelay": "34s"
      }
    ]
  }
}

The message tells you to retry in 34 seconds, but this is a daily quota: retrying in 34 seconds fails again. The quotaId is the reliable field.

Which limit did you hit?

Read quotaId in the google.rpc.QuotaFailure detail:

quotaId contains Limit What to do
PerMinute, e.g. GenerateRequestsPerMinutePerProjectPerModel-FreeTier Per-minute requests or tokens Back off and retry after retryDelay
PerDay, e.g. GenerateRequestsPerDayPerProjectPerModel-FreeTier Daily requests Stop retrying; wait for midnight Pacific, change tier or model
FreeTier The free tier's limits Linking billing moves the project to Tier 1

Google's own Gemini CLI classifies a quotaId containing PerDay or Daily as terminal instead of retrying it (UKGovernmentBEIS/inspect_ai#5526 points to the code). If the message says limit: 0, the project has no quota at all for that model; the inspect_ai project fails these immediately because they mean "the model or feature is fully restricted" (inspect_ai#3215).

Spend-based limits. On paid tiers, Google also limits spend over a rolling 10-minute window: $10 on Tier 1, $50 on Tier 2 and $200 on Tier 3. Going over returns the same 429 RESOURCE_EXHAUSTED. Google suggests waiting, sending fewer expensive requests (smaller context, shorter outputs), or requesting a rate limit increase.

Not the same as running out of credits. When a Prepay balance reaches $0, the Gemini API returns 402, not 429. Google's troubleshooting guide says not to retry 402 at all; add credits instead.

How to fix it on Google's side

  1. Check your active limits. They vary by model and tier and are shown in Google AI Studio. Google notes that the published limits aren't guaranteed.
  2. Don't create more keys in the same project. Limits are counted per project, so extra keys share the same quota.
  3. Back off on per-minute errors. The official Python SDK retries 429 and 5xx errors on its own, up to four times, starting at about 1 second and capping at 60 seconds. For direct REST calls, use exponential backoff with jitter and a maximum retry count.
  4. Stop on daily quotas. Detect PerDay in the quotaId and fail fast:
python
from google import genai
from google.genai import errors

client = genai.Client()


def quota_ids(err: errors.APIError) -> list[str]:
    body = err.details or {}
    body = body.get("error", body)
    ids = []
    for detail in body.get("details", []):
        if detail.get("@type", "").endswith("google.rpc.QuotaFailure"):
            ids += [v.get("quotaId", "") for v in detail.get("violations", [])]
    return ids


try:
    resp = client.models.generate_content(model="gemini-3.8-flash", contents="Hello")
except errors.ClientError as e:
    if e.code == 429 and any("PerDay" in q or "Daily" in q for q in quota_ids(e)):
        raise RuntimeError("Daily Gemini quota used up; retrying won't help today") from e
    raise
  1. Move off the free tier. Linking a billing account and prepaying at least $5 moves a free project to Tier 1, which Google says usually takes effect instantly. Later tiers depend on cumulative spend and account age.
  2. Move bulk work to the Batch API. Batch requests have their own rate limits, separate from interactive calls.

Call Gemini through TeamoRouter instead

If you don't want to set up Google billing for a project, TeamoRouter is another way to call Gemini. It's an API gateway with one key for Gemini, Claude, GPT and DeepSeek, billed per use from a prepaid balance with no subscription. Your Google project's quota stays as it is; requests made with a TeamoRouter key are billed to your TeamoRouter balance instead.

TeamoRouter speaks the Gemini native format (/v1beta/models/{model}:generateContent) and the OpenAI-compatible /v1/chat/completions.

  1. Create an API key in the TeamoRouter console. It starts with sk-teamo-.
  2. Top up from $5. The top-up dialog takes cards. You can also click Pay with crypto and pay with USDT, USDC or ETH from Binance, OKX or any exchange app — the checkout shows which networks your amount supports (BEP20 works from $5). You don't need a wallet extension. Step by step: Pay with USDT.
  3. Call Gemini:
bash
curl https://api.teamorouter.com/v1beta/models/gemini-3.8-flash:generateContent \
  -H "Authorization: Bearer sk-teamo-..." \
  -H "content-type: application/json" \
  -d '{"contents": [{"role": "user", "parts": [{"text": "Hello"}]}]}'

With the Google Gen AI Python SDK, set the base URL:

python
from google import genai
from google.genai import types

client = genai.Client(
    api_key="sk-teamo-...",
    http_options=types.HttpOptions(base_url="https://api.teamorouter.com"),
)
resp = client.models.generate_content(model="gemini-3.8-flash", contents="Hello")
print(resp.text)

For Gemini CLI, set these three variables (for example in ~/.gemini/.env):

bash
GOOGLE_GEMINI_BASE_URL=https://api.teamorouter.com
GEMINI_API_KEY=sk-teamo-...
GEMINI_API_KEY_AUTH_MECHANISM=bearer

GET /v1/models lists the model IDs you can use. The rest is in the API integration guide and Install and connect Gemini CLI.

FAQ

When does the daily quota reset? Requests-per-day quotas reset at midnight Pacific time, according to Google's rate limits page.

I created a new API key and still get 429. Why? Rate limits apply per project, not per key. A key in the same project shares the same quota. Check which project the key belongs to in AI Studio.

Why does the message say "retry in 34s" for a daily quota? The RetryInfo delay doesn't tell per-minute and per-day limits apart. Use the quotaId to decide whether to retry.

Is 429 RESOURCE_EXHAUSTED the same as being out of credits? No. Running out of Prepay credits returns 402. A 429 means you hit a rate or spend limit.

Next steps

Ready to connect?Log in · top up · create an API key — three steps to start.