Fix this error · Payments and AI APIs
Fix: 429 You exceeded your current quota, please check your plan and billing details
Fix OpenAI 429 insufficient_quota: billing codes vs the rate-limit 429, retry with backoff only for rate limits, and openai-node maxRetries.
This 429 from the OpenAI API is a billing error. Your organization or project has no credit left, or it hit a spend or usage limit. Waiting and retrying does not help: add credits or raise the limit in the API platform's billing settings, then try again. A different 429, Rate limit reached for …, means you sent requests too fast, and that one is fixed by slowing down and retrying with backoff.
| Fact | Detail |
|---|---|
| Error | 429 You exceeded your current quota, please check your plan and billing details. |
| Error type | insufficient_quota (newer responses also carry a specific code, such as credit_balance_exhausted) |
| Not the same as | 429 Rate limit reached for …, a temporary rate limit |
| Where you see it | Server logs, a RateLimitError from the openai package, the API response body |
| Usual cause | No prepaid credits, or an organization or project spend limit reached |
| Usual fix | Add credits or raise the limit at platform.openai.com. Do not retry until you have |
| BugTape catches it | Yes, when the error is thrown out of a request (Next.js onRequestError, uncaught). With Express, call captureException, because the handler skips 4xx |
What the error means
The OpenAI API answers 429 for two different problems. One is a rate limit: too many requests or tokens in a short time. It clears on its own, and the response can carry a Retry-After header. The other is a billing limit: the account cannot pay for more requests. It does not clear until someone changes the billing settings.
The You exceeded your current quota message has type: "insufficient_quota". OpenAI's current error reference lists the billing 429s by error.code and notes that the broader error.type can still be insufficient_quota:
| Code | Meaning |
|---|---|
credit_balance_exhausted | The organization has no prepaid credits left |
organization_spend_limit_exceeded | The organization reached its own monthly spend limit |
project_spend_limit_exceeded | The project reached its monthly spend limit |
organization_usage_limit_exceeded | The organization reached the usage limit OpenAI assigned to it |
The openai package for Node.js turns every 429 into a RateLimitError. Its message is the status followed by the API's message, which is why the log line starts with 429. The error object has status, code and type, so your code can tell the two cases apart.
Common causes
- No prepaid credits. API usage is billed separately from a ChatGPT subscription. A ChatGPT Plus plan does not include API usage.
- A spend limit was reached. The organization or project has a monthly limit, and this month's usage hit it.
- The key belongs to a different organization or project. The key you use is in a project or organization without credits, while the one you added credits to is another.
- The organization usage limit. OpenAI assigns each organization a monthly usage limit, separate from the spend limits you set.
- The rate-limit 429 instead. The message starts with
Rate limit reached for. A loop, concurrent jobs or a shared key send more requests or tokens per minute than the limit allows.
How to fix it
Fix billing, then send the next request
Open the API platform (platform.openai.com), go to Settings, Billing for credits, and Settings, Limits for organization and project limits. Check that the key you use belongs to the project you funded. Retrying a billing, spend or quota error does not restore access.
Tell the two 429s apart in code
import OpenAI from 'openai';
const BILLING_CODES = new Set([
'insufficient_quota',
'credit_balance_exhausted',
'organization_spend_limit_exceeded',
'project_spend_limit_exceeded',
'organization_usage_limit_exceeded',
]);
export function isBillingError(err: unknown): boolean {
return (
err instanceof OpenAI.RateLimitError &&
(err.type === 'insufficient_quota' || BILLING_CODES.has(err.code ?? ''))
);
}Retry only the rate limit, with backoff
The openai package already retries 429s twice by default, with a short exponential backoff, and waits for Retry-After when it is 60 seconds or less (longer values fall back to its own backoff). When the server sends an x-should-retry header, the package follows it. Otherwise it retries every 429, including billing ones, which only delays the error. Turn the built-in retries off if you run your own loop, so the two do not multiply.
const client = new OpenAI({ maxRetries: 0 });
export async function createWithRetry(params: OpenAI.Responses.ResponseCreateParamsNonStreaming, attempts = 5) {
for (let i = 0; ; i++) {
try {
return await client.responses.create(params);
} catch (err) {
if (isBillingError(err) || !(err instanceof OpenAI.RateLimitError) || i >= attempts - 1) throw err;
const retryAfter = Number(err.headers?.get('retry-after'));
const base = Number.isFinite(retryAfter) && retryAfter > 0 ? retryAfter * 1000 : 500 * 2 ** i;
await new Promise((r) => setTimeout(r, base + Math.random() * 250)); // add jitter
}
}
}To keep the package's retries, set the count instead: new OpenAI({ maxRetries: 5 }), or per request as the second argument, { maxRetries: 5 }.
Lower the request rate
Batch work, cap how many requests run at once, and avoid sharing one key between unrelated jobs. Rate limits apply to the whole organization, so teammates' usage counts too. The response headers x-ratelimit-remaining-requests and x-ratelimit-remaining-tokens show how close you are.
Return a useful answer to your own users
A billing error is not something the user can fix. Answer with a clear message and a status your client treats as temporary, and alert yourself.
if (isBillingError(err)) {
return Response.json({ error: 'The assistant is unavailable right now.' }, { status: 503 });
}How to catch it in production with BugTape
A quota error affects every user at once and does not go away, so you want to hear about it the first time. How BugTape sees it depends on where it surfaces.
- Next.js on the Node.js runtime. A
RateLimitErrorthat is thrown out of a Route Handler, Server Action or page is reported throughonRequestError. The Edge runtime is not supported. - Uncaught in Node.js. An uncaught exception or unhandled rejection is reported automatically.
- Express. The BugTape Express handler reports only errors that end in a 5xx. The OpenAI error carries
status: 429, sonext(err)with it is skipped. Report it yourself. - Caught and handled. If you catch it and return a friendly answer, nothing is reported unless you call
captureException.
import * as bugtape from '@bugtape/node';
bugtape.init({ service: 'api' }); // reads BUGTAPE_KEY
try {
return await createWithRetry(params);
} catch (err) {
if (err instanceof OpenAI.RateLimitError) {
bugtape.captureException(err, {
severity: isBillingError(err) ? 'critical' : 'medium',
extra: { code: err.code, type: err.type },
});
}
throw err;
}In a serverless function, await bugtape.flush() before the function returns so the report is sent. In Python, the openai package raises openai.RateLimitError. The BugTape Python SDK reports it when it is uncaught, when you log it at ERROR, or when you call bugtape.capture_exception() inside the except block.
Every request that fails the same way groups into one issue with a count, so a quota outage is one issue that grows. Set release so that when you mark it fixed, a report from a newer release reopens it as a regression. Your coding agent can read the issue over MCP (npx -y bugtape connect claude, or cursor or codex) and propose the retry or error-handling change. You review the pull request.
FAQ
I just added credits. Why do I still get the error?
Check that the credits went to the same organization as the key you use, and that neither the organization nor the key's project has reached a spend limit. A project spend limit stops that project even when the organization has credit.
Does ChatGPT Plus include API access?
No. ChatGPT and the API platform have separate billing. API usage is paid in the API platform's billing settings.
Should I retry insufficient_quota with exponential backoff?
No. Backoff is for the temporary rate limit. A billing error returns the same answer until the billing settings change, so retrying only delays your error and sends more requests. Check error.type and error.code and stop.
How do I know whether a 429 is a rate limit or a quota problem?
Read the message and the fields. A rate limit says Rate limit reached for …, may include a Retry-After header, and clears with time. A billing error says you exceeded your quota, or has a code such as credit_balance_exhausted or a spend-limit code.
Sources
- OpenAI: Error codes (429 billing codes,
insufficient_quotatype, do not retry billing errors, rate-limit guidance), checked 2 Nov 2026. - OpenAI: Rate limits (
Retry-After, rate-limit headers, backoff with jitter, avoid nested retries), checked 2 Nov 2026. - OpenAI Help Center: Is API usage included in ChatGPT Plus?, checked 2 Nov 2026.
- openai-node: README, Retries and source (client.ts, core/error.ts) (default 2 retries,
x-should-retry,Retry-Afterof 60 s or less, message format), checked 2 Nov 2026. - OpenAI Developer Community: insufficient_quota thread (full message text as returned by the API), checked 2 Nov 2026.
Related errors
- Stripe webhook signature verification failed:
No signatures found matching the expected signature for payload - Vercel FUNCTION_INVOCATION_TIMEOUT:
504: GATEWAY_TIMEOUT Code: FUNCTION_INVOCATION_TIMEOUT - Node.js unhandled promise rejection:
This error originated either by throwing inside of an async function without a catch block, or by rejecting a promise which was not handled with .catch()
All guides: Fix an error.
Start free. Free plan · No credit card · Set up in minutes. Or try the live demo first.