Cursor 429: why agent mode hits rate limits first
A 429 is the one error where the server is telling you exactly what to do. It answered, it understood the request, and it declined Because you sent too much, too fast.
The reason it shows up in Cursor earlier than in a chat app is concurrency. A single message you send does not produce a single request. Agent mode runs a loop: plan, call a tool, read the result, decide, call again. Each step is a separate request, and several can be in flight at once. So the request rate you are actually generating is not the rate at which you type.
https://aicomp.ai/v1).
Create one free →
Three different limits wear the same status code
They need three different responses, so identify which one you hit before changing anything.
| Limit | What it counts | What it looks like | What actually helps |
|---|---|---|---|
| Request rate | Calls per minute | Fails at the start of a burst, recovers on its own | Space out requests; reduce parallel agent steps |
| Token rate | Tokens per minute | Fails on large contexts, fine on small ones | Shorten the context, not the number of calls |
| Concurrency | Simultaneous in-flight calls | Fails only when several steps run at once | Serialise the loop |
You can tell them apart by what succeeds. Small requests that keep working while big ones fail means you are against a token limit. A burst that fails and then recovers a minute later without you changing anything means a request-rate limit. Failures that appear only when the agent parallelises mean concurrency.
Read Retry-After before you guess a delay
Most endpoints include how long to wait. Hard-coding a fixed sleep is the common mistake, too short and you generate another 429, too long and you stall a session that could have resumed sooner.
# Ask the endpoint what it will accept, and read the headers it sends back
curl -s -D - -o /dev/null --max-time 20 https://aicomp.ai/v1/chat/completions \
-H "Authorization: Bearer $OPENAI_API_KEY" \
-H "Content-Type: application/json" \
-d '{"model":"claude-sonnet-5","messages":[{"role":"user","content":"hi"}],"max_tokens":16}' \
| grep -iE "^(HTTP/|retry-after|x-ratelimit|ratelimit)"
Retry-After is in seconds. The x-ratelimit-* headers, when present, tell you how much of the budget is left Which is more useful than the error, because it lets you slow down before you are refused rather than after.
Back off exponentially with a ceiling, and add jitter so parallel retries do not resynchronise into another burst:
import random, time
def backoff(attempt, retry_after=None, cap=60):
if retry_after:
return min(float(retry_after), cap)
return min(2 ** attempt, cap) + random.uniform(0, 1)
Honour Retry-After when the server sends one; fall back to exponential only when it does not. And cap the retries — a loop that retries forever converts a rate limit into a much longer outage and a bigger bill.
The agent-specific fixes
Shorten sessions before slowing them down. Every agent turn re-sends the accumulated conversation, so a 20-turn session is paying for turn 1's tokens twenty times. Ending a task in fewer turns reduces the token rate without reducing throughput, which is the only change that helps a token limit.
Cut tool output, not tool calls. Each file read and command result becomes input on the next turn. Reading a large file "just to check" adds tokens to every remaining turn in the session, not just one.
Do not retry a failed tool call blindly. A retry re-sends the full context and produces nothing. On a long session, a retry near the end is one of the most expensive single events in it, and if the failure was a 429, the retry is also the thing most likely to get refused again.
When switching models is the fix
Rate limits are often per model, not per account. A frontier model under load and a smaller model with headroom can be different budgets on the same key. If your task does not need the largest model (classification, summarising, mechanical edits) routing that slice elsewhere takes pressure off the limit you are hitting.
Rates differ by model, and the model price index is the place to check which ones have room in your budget rather than which ones are cheapest in the abstract.
That is also the argument for one endpoint rather than several vendor keys: the fallback is a model-ID change in the same place, not a new credential in a new dashboard.
FAQ
FAQ
Why do I get 429 in Cursor but not in the API directly?
Because agent mode multiplies your request count. One prompt becomes a loop of tool calls and follow-ups, several potentially in flight at once, each carrying the full accumulated context. The request rate you generate is decoupled from the rate at which you type, which is why the same key can look fine in a chat client and limited in an agent.
Should I retry immediately or wait?
Wait, and wait the amount the server asks for. A Retry-After header is the endpoint telling you its own reset window; ignoring it in favour of an immediate retry usually produces a second 429 and costs a full context re-send. Exponential backoff with jitter is the fallback when no header is sent.
Does a bigger context window make rate limits worse?
It makes token-rate limits worse and request-rate limits unchanged. If large requests fail while small ones succeed, you are against a token budget and shortening the context is the lever. If failures track bursts rather than size, context length is irrelevant and you need to space requests out.
Is 429 the same as a quota error?
Not usually. A rate limit is temporary and resets within seconds or minutes. A quota is a budget for a billing period and will not clear on its own. The practical tell is whether waiting helps: if it does, it was a rate limit.
Can unlimited retries fix it?
No, and they make it worse. Each retry re-sends the whole context, so an uncapped retry loop adds load to the limit you are hitting and cost to a session that is not making progress. Cap the attempts, then surface the failure.
Related
- Cursor API key errors — 401 and 403, which a 429 is not
- Cursor agent tool call errors — failures inside the loop rather than at the rate limit
- Claude Code 429 rate limit — the same limit in a different client
- LiteLLM retries and timeouts — retry policy when you control the client
- What hitting the context limit costs — why long sessions cost twice
- Monitoring API spend — see the load before you are refused