429 RESOURCE_EXHAUSTED at 0.03% of quota — reproducible across projects, tiers and endpoints

Model: gemini-3.1-flash-lite Observed: August 5–6, 2026 (CEST) Region: Czech Republic

Summary

Roughly 40% of my requests fail with 429 RESOURCE_EXHAUSTED while the Cloud Console reports my quota usage at 0.03%. I have ruled out every client-side cause I can think of, including creating a brand new project on a different tier. I would appreciate any pointer as to what resource is actually being exhausted.

A secondary issue: the OpenAI-compatibility endpoint reports this same condition as 400 INVALID_ARGUMENT, which sent me looking for a malformed request for two days.

Reproduction

Minimal request, native endpoint, no SDK:

curl -X POST
https://generativelanguage.googleapis.com/v1beta/models/gemini-3.1-flash-lite:generateContent
-H “x-goog-api-key: $KEY”
-H “Content-Type: application/json”
-d ‘{“contents”:[{“parts”:[
{“fileData”:{“fileUri”:“https://bb0536d6afeb6d2c8a69b249107861bf.cdn.bubble.io/f1785960536931x858895192810575800/UcTest_04A.jpeg",“mimeType”:"image/jpeg”}},
{“text”:“Describe this image in one sentence.”}
]}]}’

Run five times with 30-second gaps between calls:

attempt 1: 200
attempt 2: 429
attempt 3: 200
attempt 4: 200
attempt 5: 429

Successful responses are correct and complete. Failures return:

{“error”:{“code”:429,“message”:“Resource has been exhausted (e.g. check quota).”,“status”:“RESOURCE_EXHAUSTED”}}

What I ruled out

Quota. Cloud Console → Quotas, filtered to Gemini API, shows “Current usage > 90%: 0” across all 1,858 quotas. Request limit per model per minute: 1.25 of 4,000 (0.03%). Input token count limit per minute: 858 of 4,000,000 (0.02%). No quota is anywhere near its ceiling.

Rate limiting. AI Studio Rate Limit page: 3/4K RPM, 8.9K/4M TPM, 66/150K RPD. Adding 30-second gaps between calls improved the failure rate from ~40% to ~20% but did not eliminate it — and the very first call after a multi-minute idle period has failed on several occasions.

Billing. Tier 1, active billing account, positive prepay balance (paid by card, ~2% consumed). No warnings on the billing page.

Project and key. I created a new project with a new API key on the Free Tier. Same behaviour, same rate: 3 failures out of 5 calls.

Endpoint. Both /v1beta/models/...:generateContent and /v1beta/openai/chat/completions fail at comparable rates.

Payload. Fails identically with a 5,085-token prompt and with an 8-token ASCII prompt. Image is 1,064 tokens either way and is publicly reachable — successful calls fetch and read it correctly. maxOutputTokens raised from 1,500 to 5,000 with no effect.

Client. Reproduces from both a server-side HTTP client and plain curl on a local machine, in the same minutes.

Secondary issue: error code mistranslation

Through /v1beta/openai/chat/completions this same condition surfaces as:

{“error”:{“code”:400,“message”:“Request contains an invalid argument.”,“status”:“INVALID_ARGUMENT”}}

A 400 tells the caller their request is malformed, so I spent two days auditing my request body, prompt encoding, image URL and token limits — none of which were the problem. The native endpoint returned 429 on the first try and immediately pointed in the right direction. If the compatibility layer passed the underlying status through, this would have been a ten-minute diagnosis.

I also saw one response with an empty content: {} and totalTokenCount == promptTokenCount, i.e. a 200 with no output tokens generated. That may be the same condition surfacing a third way.

Context

AI Studio Usage shows both 400 BadRequest and 429 TooManyRequests bars over the affected period, alongside some 503 ServiceUnavailable. The status page at he official status page has reported “All Systems Operational” throughout. Third-party monitoring picked up user reports of sustained 503s across several Flash models over the same window, so I do not believe this is specific to my account.

The Cloud Billing console currently displays a banner about cost data delays affecting multiple GCP services since August 1, 2026. I mention it only in case the billing pipeline and the quota enforcement path share state — I have no evidence either way.

Question

Which resource is being reported as exhausted when every visible quota sits below 0.1%? Is there a limit dimension not surfaced in Cloud Console quotas or the AI Studio rate limit page — concurrency, per-region capacity, or vision-specific throughput?

If this is capacity-related rather than quota-related, a 503 would let callers apply the right retry strategy. A 429 implies backing off will help; in my measurements the failures arrive in clusters of up to nine consecutive calls, so it largely does not.

Happy to provide request IDs, timestamps or project numbers.

Not a developer here but it feels and sounds like what I’m experiencing. Thank you for putting it into terms I could not relay.

Since when are you experiencing that?

two days ago i reported it as lag… double charging prompts. then yesterday i didnt do much and this morning it wasted 17 RPD for 1 prompt

Hello @Petr_Hlavka ,

If you’re receiving 429’s and have checked no rate limit was breached for the period, please add your details to this form & we’ll check it out.

Hello, I already did that. All the details are in this post and in the related form.
Thank you.

Corroborating this from a different project, same window — paid tier, native generativelanguage REST endpoint (streaming, ?alt=sse), Vercel AI SDK on Node 24, requests originating from us-east.

Same shape as yours: 429 RESOURCE_EXHAUSTED with a bare body — no QuotaFailure details, no RetryInfo, and no Retry-After header:

{
“error”: {
“code”: 429,
“message”: “Resource has been exhausted (e.g. check quota).”,
“status”: “RESOURCE_EXHAUSTED”
}
}

The responses come back in ~360 ms (server-timing: gfet4t7; dur=359), which doesn’t look like per-minute rate limiting — it reads like a capacity rejection. Our 3 exponential retries all fail inside the same second, so the whole user-facing request dies.

Failure rate from our own telemetry (failed calls / total calls per day, UTC), ~5-7k calls/day, volume flat across the whole period:

Date gemini-3.6-flash gemini-3.1-flash-lite
Jul 30 0.2% 0.2%
Jul 31 0.3% 0%
Aug 3 0.4% 0
Aug 4 2.0% 0
Aug 5 3.2% 0
Aug 6 5.9% 1
Aug 7 4

Two notes on the table so it isn’t misread: the Aug 6 figure covers 00:00–18:00 UTC only, and I left Aug 7 blank for gemini-3.6-flash, because at 18:13 UTC on Aug 6 we deployed a
change on our side affecting thg shown above is untouched
standard-tier traffic, and `gem touched at all — that column is
clean end to end.

So this doesn’t look specific t see the same climb ongemini-3.6-flash, starting Aug 4, roughly an order of magnitude above our baseline of 0.2-0.4%.
Questions that would unblock us- Are these quota-based or capalureorRetryInfo` in thepayload, there’s no way to tellud console shows us nowhere nearour limits either.

  • What backoff is recommended fno Retry-After is returned?
  • Is there any status surface where this would show up? status.cloud.google.com has no component for generativelanguage.googleapis.com, so a degradation here appears to be invisible to customers by design.

Happy to share project number ahat helps narrow it down.

I am seeing what appears to be the same issue in my environment, and I was able to reduce it to a very small reproducible request.

I am using:

Model: gemini-3.5-flash-lite
Tier: Tier 1
API: Gemini API generateContent
Endpoint: https://generativelanguage.googleapis.com/v1beta/models/gemini-3.5-flash-lite:generateContent

The Rate Limit page in AI Studio shows that the project is nowhere near its RPM, TPM, or RPD limits. The displayed usage is approximately:

RPM: 2 / 4,000
TPM: 7.82K / 4M
RPD: 12 / 150K

To isolate the problem, I created a minimal test separate from my production application.

  1. Text-only request

Using the same API key, project, and model, this request succeeds:

{
“contents”: [
{
“role”: “user”,
“parts”: [
{
“text”: “Reply with OK only.”
}
]
}
]
}

The response is HTTP 200:

HTTP status: 200
text: OK
promptTokenCount: 6
candidatesTokenCount: 1
totalTokenCount: 7
serviceTier: standard

  1. The same request with one public JPEG URL added

I then added only one fileData.fileUri part:

{
“contents”: [
{
“role”: “user”,
“parts”: [
{
“text”: “Reply with OK only.”
},
{
“fileData”: {
“fileUri”: “https//auctions.c.yimg.jp/images.auctions.yahoo.co.jp/image/dr000/auc0204/user/63a6718d196de03959df5f20f652789057e66a64b65849ac1c61b2c80adfd907/i-img800x1199-17774338629983njxg7z178522.jpg”,
“mimeType”: “image/jpeg”
}
}
]
}
]
}

This image is publicly accessible over HTTPS and does not require authentication, cookies, or a login. It can also be opened directly in a private/incognito browser session.

With this single image added, the API returns HTTP 429:

{
“error”: {
“code”: 429,
“message”: “Resource has been exhausted (e.g. check quota).”,
“status”: “RESOURCE_EXHAUSTED”
}
}

There is no QuotaFailure, quota metric, quota limit, RetryInfo, or retry delay in the response.

So the minimal reproduction is:

Text only
→ HTTP 200

Exactly the same request + one public JPEG via fileData.fileUri
→ HTTP 429 RESOURCE_EXHAUSTED

In my actual application, I normally send three public image URLs using fileData.fileUri, and the same 429 RESOURCE_EXHAUSTED occurs there as well.

I initially suspected the larger prompt, multiple images, JSON schema, or normal RPM/TPM/RPD rate limits. However, the minimal test above shows that even adding a single public JPEG URL to a tiny six-token text request is sufficient to trigger the error.

I have also reproduced an image-related 429 using another Google account/project, so this does not appear to be limited to a single API key or project.

The problem has also persisted after waiting and retrying on different days, so it does not appear to be a short-lived RPM/TPM rate-limit event.

Based on this reproduction, I suspect the issue may be related to the external file ingestion/fetch path used by fileData.fileUri, rather than the normal user-visible RPM/TPM/RPD quotas.

I will also submit the unexpected-429 reporting form referenced by Google staff, including the affected Project Number and screenshots of the AI Studio Rate Limit page.

Please let me know if any additional request/response details or timestamps would be useful for investigation.

God bless you! It helped me to solve the problem it seems…

Update: The issue is still reproducible in my environment.

I also tested with gemini-3.6-flash using a completely different public file and domain:


Model: gemini-3.6-flash
File: https://ontheline.trincoll.edu/images/bookdown/sample-local-pdf.pdf
HTTP status: 429

Response:


{
  "error": {
    "code": 429,
    "message": "Resource has been exhausted (e.g. check quota).",
    "status": "RESOURCE_EXHAUSTED"
  }
}

So this does not appear to be specific to Yahoo-hosted JPEG images or to gemini-3.5-flash-lite. It appears to affect the external file ingestion path more generally.

Hello @kk_oo1 ,

Thank you for sharing the detailed reproduction steps, We have escalated this issue and are looking into it.

Guys, inline base64 is a way how to bypass this issue.

Thank you for the update and for escalating the issue.

The issue is still reproducible in my environment.

I understand that using inline Base64 can be used as a workaround. However, for a multi-user application, downloading the image files on our server and then uploading them again as Base64 increases server-side network traffic, memory usage, and processing load compared with using fileData.fileUri.

Therefore, we would appreciate it if the issue with the external file ingestion path could be fixed so that fileData.fileUri can be used normally again.

Please let me know if you need any additional reproduction data or testing from my side.

Thanks for sharing this.

Just a note on the performance concern with the Base64 workaround: it depends on where you do the conversion.

In our setup the file is converted to Base64 in the user’s browser, before it ever reaches our backend, so there’s no server-side download-and-re-upload cycle. No extra server traffic, no memory overhead — the cost sits with the client that just picked the file anyway.

We migrated a production receipt-OCR pipeline from fileData.fileUri to inline Base64 across ~33 test documents (JPEG, PNG, PDF). Two side effects worth mentioning: median processing time dropped by roughly half, since Google no longer has to fetch the file from our CDN, and PDF input started working.

For anyone hitting this from a browser-based app, client-side conversion may be a better answer than waiting for the ingestion path to be fixed. It’s a different architecture rather than a workaround.

Any updates on this?

It is 100% reproducible on both Gemini 3.5 flash and Gemini 3.6 flash (it’s fine on gemini 2.5 flash). As long as you include an external resource via this file URI (check the sample below, which is taken from the gemini api doc), you run into the issue every time. This is going to impact a lot of customers. This is definitely a serious incident.

[
{ text: "Describe this briefly." },
{
fileData: {
mimeType: "application/pdf",
fileUri: "https://ontheline.trincoll.edu/images/bookdown/sample-local-pdf.pdf"
}
}
]

I can’t believe this 100% reproduciable bugs hasn’t been fixed for a week??

And most of us had to spend God knows how long to figure out what the problem was.

Unacceptable.

Hi there! Dealing with the Gemini API image understanding resource was an absolute waste of time for me as well, just like for everyone here… I spent hours trying to figure out what was wrong: checking my quota, inspecting CDN limitations, digging through the documentation, and even asking Gemini AI itself!

Please, update the documentation to clarify that when you mention ‘public URLs’, you essentially mean object URLs living within Google’s own storage services (such as the Google Files API or Google Cloud Storage buckets).

My images are stored in DigitalOcean Spaces, and the only way to avoid the 429 Resource has been exhausted error was to temporarily upload those files to the Google Files API first and then pass the resulting Google file URIs into client.interactions.create(). It’s not ideal to manage an extra upload step, but it’s definitely better than sending them as base64 payloads.