OpenAI Chat Completions HTTP 500 5 min read

OpenAI API 500 Internal Server Error — How to Fix It

A 500 Internal Server Error from the OpenAI API (along with 502 Bad Gateway and 503 Service Unavailable) is an OpenAI-side failure — not your key, not your code. These are transient and safe to retry with backoff. This guide shows how to tell a real outage apart from a bad request, and how to build retry logic that keeps your app running.

OpenAI API live status

OpenAI API — live status

Updated every 5 minutes · Full incident history →

Check now →

What does a 500 (or 502 / 503) mean from OpenAI?

A 500 Internal Server Error means “the server had an error while processing your request.” A 503 Service Unavailable means OpenAI is overloaded or temporarily down, and a 502 Bad Gateway means an upstream proxy failed. All three are OpenAI-side and retriable. They are fundamentally different from client errors like 400 and 401:

Code Meaning Fix
400 Your request is malformed (bad params, invalid schema) Fix the input — do NOT retry
401 Invalid or missing API key Check key at platform.openai.com
429 Your rate limit or quota is exhausted Back off, or add credit / raise limits
500 / 502 / 503 OpenAI's servers failed or are overloaded Retry with exponential backoff

One nuance: a 500 is usually OpenAI's fault, but it can occasionally be triggered on your side by a malformed streaming request or an extremely large payload (a giant prompt or a pathological max_tokens). If a 500 reproduces on one specific request while everything else works, treat that request as the suspect (see step 4). A 500 across all your requests is an OpenAI incident.

5 steps to fix and prevent 500 errors

1

Check whether it is an OpenAI outage

Before writing any retry code, find out whether OpenAI is having a platform-wide problem or whether your 500s are isolated to one request. The fastest signal is the Prismix status dashboard, which polls the OpenAI API and aggregates incidents in real time.

Diagnosis checklist

  • Open prismix.dev/service/openai — an active incident appears at the top with a timeline.
  • A wave of 500s across many users or many of your requests = OpenAI-side incident. Back off and wait.
  • Only one request returns 500 while others succeed? That is a payload problem, not an outage — skip to step 4.
  • Also check status.openai.com for OpenAI's own incident page.
2

Let the SDK retry automatically (simplest fix)

The official openai Python and Node SDKs automatically retry connection errors and 5xx responses (including 500, 502, and 503) with exponential backoff. The default is 2 retries — raise it for production workloads:

# Python — increase SDK retries to 5 (covers most transient 500/502/503 spikes)
import os
from openai import OpenAI

client = OpenAI(
    api_key=os.environ["OPENAI_API_KEY"],
    max_retries=5,   # default is 2; the SDK retries 5xx and connection errors
    timeout=60.0,    # seconds per attempt
)

resp = client.chat.completions.create(
    model="gpt-4o",
    messages=[{"role": "user", "content": "Hello"}],
)
// TypeScript — same pattern
import OpenAI from 'openai';

const client = new OpenAI({
  apiKey: process.env.OPENAI_API_KEY,
  maxRetries: 5,
  timeout: 60_000,  // ms
});

With max_retries=5, the SDK waits roughly 1 s, 2 s, 4 s, 8 s, and 16 s (with jitter) before surfacing the error. This alone resolves the vast majority of short 500 waves with zero extra code.

3

Add explicit exponential backoff for batch jobs

For batch processing or long-running server jobs, write an explicit retry wrapper. It should retry only the server-side 5xx codes, cap the wait time, add jitter, and re-raise client errors (400/401) immediately so a broken request does not loop forever:

import os
import time
import random
from openai import OpenAI, APIStatusError

client = OpenAI(api_key=os.environ["OPENAI_API_KEY"], max_retries=0)

RETRIABLE = {500, 502, 503}  # server-side only

def create_with_backoff(max_attempts: int = 6, **kwargs):
    """Retry OpenAI 5xx server errors with exponential backoff + jitter."""
    for attempt in range(max_attempts):
        try:
            return client.chat.completions.create(**kwargs)
        except APIStatusError as e:
            if e.status_code not in RETRIABLE:
                raise  # 400/401/429 are not server faults — handle separately
            if attempt == max_attempts - 1:
                raise
            wait = min(60.0, (2 ** attempt) + random.uniform(0, 1))
            print(f"OpenAI {e.status_code} server error. Retry {attempt + 1}/{max_attempts - 1} in {wait:.1f}s")
            time.sleep(wait)

# Usage
response = create_with_backoff(
    max_attempts=6,
    model="gpt-4o",
    messages=[{"role": "user", "content": "Hello"}],
)
// TypeScript async version — catch OpenAI.APIError and check err.status
import OpenAI from 'openai';

const client = new OpenAI({ apiKey: process.env.OPENAI_API_KEY, maxRetries: 0 });

const RETRIABLE = new Set([500, 502, 503]);

async function createWithBackoff(
  params: OpenAI.ChatCompletionCreateParamsNonStreaming,
  maxAttempts = 6,
) {
  for (let attempt = 0; attempt < maxAttempts; attempt++) {
    try {
      return await client.chat.completions.create(params);
    } catch (e) {
      if (!(e instanceof OpenAI.APIError) || !RETRIABLE.has(e.status ?? 0)) throw e;
      if (attempt === maxAttempts - 1) throw e;
      const wait = Math.min(60_000, (2 ** attempt) * 1000 + Math.random() * 1000);
      console.warn(`OpenAI ${e.status} — retry ${attempt + 1} in ${(wait / 1000).toFixed(1)}s`);
      await new Promise(r => setTimeout(r, wait));
    }
  }
}
4

Reduce payload & avoid pathological inputs

If a 500 reproduces on one specific request while the rest of your traffic succeeds, it is almost certainly the request, not an outage. An extremely large prompt, a huge max_tokens, or a malformed function / tool schema can push the backend into an internal error instead of a clean 400. Shrink the request and stream long outputs to isolate the trigger:

# A single giant, buffered request is the most common self-inflicted 500.
# Prefer smaller, streamed calls over one enormous completion.
stream = client.chat.completions.create(
    model="gpt-4o",
    messages=messages,
    max_tokens=1024,   # avoid pathologically large output caps
    stream=True,       # stream long output instead of buffering it all
)
for chunk in stream:
    delta = chunk.choices[0].delta.content or ""
    print(delta, end="")
  • Validate tool/function schemas: a malformed tools definition can surface as a 500 rather than a 400 — double-check the JSON Schema.
  • Trim the prompt: if you are near the model's context window, a 500 can appear before you hit a clean context-length error. Cut input tokens and retry.
  • Test the request in isolation: replay the exact failing payload with a tiny max_tokens. If it still 500s alone, the payload is the cause.
5

Add a circuit breaker for production

During a prolonged 500/503 incident, retrying every request just queues up a backlog and hammers a backend that is already failing. A circuit breaker stops sending requests after a failure threshold, waits a fixed recovery window, then probes once before resuming:

import time
from openai import APIStatusError

class CircuitBreaker:
    def __init__(self, failure_threshold=3, recovery_timeout=60):
        self.failures = 0
        self.threshold = failure_threshold
        self.timeout = recovery_timeout
        self.opened_at = None
        self.state = "closed"  # closed | open | half-open

    def record_failure(self):
        self.failures += 1
        if self.failures >= self.threshold:
            self.state = "open"
            self.opened_at = time.monotonic()
            print(f"Circuit OPEN — pausing OpenAI calls for {self.timeout}s")

    def record_success(self):
        self.failures = 0
        self.state = "closed"

    def allow_request(self) -> bool:
        if self.state == "closed":
            return True
        elapsed = time.monotonic() - self.opened_at
        if elapsed >= self.timeout:
            self.state = "half-open"
            return True  # probe request
        return False

breaker = CircuitBreaker()

def safe_create(**kwargs):
    if not breaker.allow_request():
        raise RuntimeError("OpenAI circuit open — skipping request")
    try:
        result = client.chat.completions.create(**kwargs)
        breaker.record_success()
        return result
    except APIStatusError as e:
        if e.status_code in (500, 502, 503):
            breaker.record_failure()
        raise

Get an email the next time OpenAI goes down

Outage alerts for OpenAI, straight to your inbox. No account needed, unsubscribe in every email.

Watching more than one service? A free account covers 5 services + a daily digest — and Pro is currently free.

FAQ

Is a 500 my fault or OpenAI's?

Almost always OpenAI's. A 500 Internal Server Error means “the server had an error while processing your request” — a backend failure, not a bad key or bad input. The rare exception is a malformed streaming request or an extremely large payload, which can surface as a 500 instead of a 400. If a 500 reproduces on one specific request only, inspect that request; if it hits everything, it is an OpenAI incident.

Should I retry a 500?

Yes — with exponential backoff. 500, 502, and 503 are transient server errors, and the openai SDK already retries them for you. Do not blindly retry a 400 (malformed request) or 401 (bad key): those fail identically on every attempt until you fix the request or the credentials.

What is the difference between a 500 and a 429?

A 429 means your account exceeded a rate limit or ran out of quota/credit — the request was rejected before reaching the model. A 500/502/503 means OpenAI's servers failed on an otherwise valid request. Both can be retried with backoff, but a 429 also needs you to slow down or add credit, while a 500 usually clears on its own.

Am I charged for a 500?

No. A failed request that returns 500/502/503 is not billed — you only pay for successful completions. If a streaming response fails partway through, you are billed only for tokens actually delivered before the error, which is typically zero on an upstream failure.

How long do OpenAI 500 waves last?

Usually just minutes — a short spike clears once OpenAI's backend recovers. Bigger infrastructure incidents can run 30–120 minutes. Check prismix.dev/service/openai for the incident timeline and status.openai.com for OpenAI's own updates. If an incident is active, back off hard rather than retrying tightly.

Related guides