OpenAI insufficient_quota: tell a quota 429 from a rate limit 429

By Sazabi Team

Failure facts checked on the vendor’s docs on Nov 8, 2026.

Searches for this error usually start with insufficient_quota. OpenAI's error reference lists four billing-related codes under it, and they all arrive as HTTP 429, the same status as an ordinary rate limit. That is how a billing problem gets mistaken for traffic and retried for hours.

The four codes

error.codeCause, per OpenAIHow it clears
credit_balance_exhaustedThe organization has no prepaid credits leftAdd credits
organization_spend_limit_exceededThe organization hit a hard spend limit you configuredRaise or remove the limit, or wait for the monthly reset
project_spend_limit_exceededOne project hit its own hard limitChange that project's limit
organization_usage_limit_exceededThe organization reached the usage limit OpenAI assignedRequest a higher approved limit or contact support

For these errors OpenAI says to read error.code and not rely on error.type, which can still say insufficient_quota for several of them. A handler that branches on type alone will lump them together.

Two of the limits are yours, and two are OpenAI's view of your account. Spend limits are set by someone on your team, often long ago and forgotten. The usage limit follows your tier: the rate limit guide lists $100, $500, $5,000 and $200,000 a month for Free, Build, Launch and Grow. It also says the approved usage limit is separate from spend limits, so you can hit either first.

Why retries make it worse

OpenAI states that retrying billing, spend or quota errors will not restore access. A client that treats every 429 as transient will burn its retry budget, hold connections and queue depth open, and can delay the alert that tells a human to add credit. Compare that with a true rate limit, which clears in seconds and may come with Retry-After. See OpenAI rate limits for that side.

Hard spend limits also have a lag. OpenAI says enforcement is not instantaneous and recorded spend can slightly exceed the cap, so a job can keep succeeding for a short time after you cross the line and then fail all at once.

What to log

On every failed call, keep the error.code, the error.type, the HTTP status, the model, the project or key label and your own caller name. Add a retryable field set by your classifier, so a later query can count calls retried when they should not have been.

BILLING_CODES = {
    "credit_balance_exhausted",
    "organization_spend_limit_exceeded",
    "project_spend_limit_exceeded",
    "organization_usage_limit_exceeded",
}

def classify_openai_429(body: dict) -> str:
    err = body.get("error", {})
    code = err.get("code")
    if code in BILLING_CODES:
        return "quota"      # do not retry; page a human
    if err.get("type") == "insufficient_quota" and code != "slow_down":
        return "quota"      # unknown billing code under the broader type
    if code == "slow_down":
        return "ramp"       # retry slower
    return "rate_limit"     # retry with Retry-After and jitter

What to alert on

  • Any billing code at all. Unlike rate limits, there is no healthy background level of these, so a single occurrence in production is worth a message to whoever owns billing.
  • The count of retries after a quota classification. It should be zero.
  • Spend against the month. The logs only show tokens, not dollars, so multiply by your price table and compare the running total with each spend limit and with your tier's usage limit. Reaching 80% of the limit in the first half of the month is an early warning.
  • A sudden rise in tokens per request from one caller. Runaway prompts are a common way to use up credit.

Example: a project cap hit mid-job

This is an example, not output from a real project. A made-up report-builder service shares an OpenAI project with a backfill script.

2026-11-19T14:02:11Z msg="vendor call" vendor=openai project=reports status=200 caller=report-builder
2026-11-19T14:02:12Z msg="vendor call" vendor=openai project=reports status=200 caller=backfill
2026-11-19T14:02:44Z msg="vendor call" vendor=openai project=reports status=429 error_code=project_spend_limit_exceeded caller=backfill
2026-11-19T14:02:45Z msg="vendor call" vendor=openai project=reports status=429 error_code=project_spend_limit_exceeded caller=report-builder

Both callers fail within a second, with a billing code, on one project. Tokens-per-minute headers would still show room. The fix is a decision about the project's limit, and the backfill is the first thing to question.

Checklist

  1. Branch on error.code, never on error.type or status alone.
  2. Mark the four billing codes non-retryable and fail fast.
  3. Alert a human on the first billing code.
  4. Set spend alerts below every hard limit, so someone is told before traffic stops.
  5. Write down who owns each limit, per organization and per project.
  6. Keep a fallback path, such as a queue or a second provider, for features that cannot stop.

Related reading: monitoring third-party dependencies, capacity risks and LLM spend spikes. If your call logs reach Sazabi, the agent can watch for these codes.

OpenAI exhausted quota facts

  • Four billing-related 429 codes: credit_balance_exhausted, organization_spend_limit_exceeded, project_spend_limit_exceeded and organization_usage_limit_exceeded all return HTTP 429. (OpenAI docs, accessed Nov 8, 2026)
  • error.type can still say insufficient_quota: OpenAI says to inspect error.code for billing errors because the broader error.type can still be insufficient_quota. (OpenAI docs, accessed Nov 8, 2026)
  • Retrying does not help: Retrying billing, spend or quota errors will not restore API access until credits or limits change. (OpenAI docs, accessed Nov 8, 2026)
  • Hard limits are not instant: Enforcement of a hard spend limit is not instantaneous, so recorded spend can slightly exceed the configured amount. (OpenAI docs, accessed Nov 8, 2026)
  • Approved monthly usage limit per tier: Each organization has an OpenAI-assigned monthly usage limit tied to its usage tier, separate from any spend limit you configure. (OpenAI docs, accessed Nov 8, 2026)

With Sazabi

The Sazabi agent automatically sets up sensors for your project and maintains them over time. When your code calls OpenAI, it watches a question like this one:

Tell me when OpenAI calls start failing with a spend or credit error code, or when monthly OpenAI usage is on course to reach its limit early.

When the answer turns abnormal, Sazabi investigates and opens an issue. Approaching a limit covers the signal behind it.

Frequently Asked Questions

What does insufficient_quota mean?

Your account ran out of something money-shaped: prepaid credits, a spend limit you set, or the monthly usage limit OpenAI assigns to your tier. It is not a per-minute rate limit, and waiting a minute will not clear it.

How do I tell a quota 429 from a rate limit 429?

Read error.code. Codes ending in spend_limit_exceeded or usage_limit_exceeded, and credit_balance_exhausted, are billing errors. A rate limit 429 carries a request or token message, or slow_down, and may include Retry-After.

When does a hard spend limit reset?

At the next monthly cycle, unless you raise or remove the limit first. Traffic resumes after the change propagates.

Can I get a warning before the limit hits?

Yes, in two places. OpenAI spend alerts notify you at thresholds you set and keep sending traffic. Your own logs can also track spend, so you can see a projection before the cap.

Sources

  1. The four billing-related 429 codes, the insufficient_quota error.type note and the statement that retrying does not restore access (accessed Nov 8, 2026)
  2. Hard limit behavior, spend alerts, monthly reset and the steps to restore API traffic (accessed Nov 8, 2026)
  3. Usage tiers and their monthly usage limits, and the difference between rate limits and the approved usage limit (accessed Nov 8, 2026)