FehlerbehebungAnleitung
429 Too Many Requests von einer KI-API: Wiederholungen mit Backoff
Was ein 429 von einer KI-API bedeutet und wie man damit umgeht: exponentielles Backoff mit Jitter, Retry-After und Agenten-Parallelität, mit Python- und JavaScript-Code.

Auf dieser Seite
Ein 429 Too Many Requests von einer KI-API bedeutet, dass die Anfrage abgelehnt wurde, weil du zu viel zu schnell gesendet hast oder ein Limit deines Kontos erreicht wurde. Die Lösung ist, zu warten und mit exponentiellem Backoff und Jitter erneut zu versuchen, den Retry-After-Header zu verwenden, wenn die Antwort einen enthält, und zu begrenzen, wie viele Anfragen dein Agent parallel sendet. Wiederhole keinen 429, der eigentlich ein Ausgaben- oder Guthabenlimit ist: Warten behebt das nicht.
Dieser Leitfaden basiert auf den offiziellen Rate-Limit-Leitfäden von OpenAI und Anthropic, beide geprüft am 22. Oktober 2026. Keine der beiden Seiten zeigt ein Datum der letzten Aktualisierung.
Was ein 429 bedeutet#
OpenAI beschreibt einen 429 als eine Anfrage, die abgelehnt wurde, weil ein Rate-Limit überschritten wurde (rate_limit_error, mit dem Code slow_down, wenn der Traffic zu schnell ansteigt), oder weil ein hartes Ausgabenlimit erreicht wurde. Anthropic verwendet ebenfalls rate_limit_error für 429. Ein 429 wegen Ausgabenobergrenze hat keinen retry-after-Header und schlägt weiter fehl, bis der Zugang wiederhergestellt ist.
Zwei Nachbarn sind leicht damit zu verwechseln. OpenAIs 503 server_ und Anthropics 529 overloaded_ sind Überlastungszustände, nicht dein Rate-Limit. Sie werden üblicherweise mit derselben Retry-Schleife behandelt, sagen aber etwas anderes über die Ursache aus.
Es gibt also drei Fälle, und jeder erfordert eine andere Reaktion:
Tabelle nach rechts scrollen →
| Antwort | Ursache | Was zu tun ist |
|---|---|---|
| 429 Rate-Limit | Zu viele Anfragen oder Tokens pro Minute | Warten, mit Backoff erneut versuchen |
| 429 Ausgaben- oder Guthabenlimit | Kontolimit erreicht | Nicht wiederholen; Limit anpassen oder Guthaben aufladen |
| 503 / 529 überlastet | Anbieterseite ist ausgelastet | Mit Backoff erneut versuchen, mit Obergrenze |
Wenn dein Guthaben aufgebraucht ist, lies stattdessen den Fehler "nicht genügend Tokens". Für Fehler auf Netzwerkebene wie Timeouts und abgelehnte Verbindungen siehe häufige Verbindungsfehler.
Lies die Header, bevor du eine Verzögerung errätst#
OpenAI dokumentiert diese Header bei rate-limitierten Antworten: Retry-After, und x-, x-, x- mit -tokens-Varianten. Andere APIs senden möglicherweise eine Teilmenge oder keinen davon, also schreibe den Client so, dass er Retry-After verwendet, wenn es vorhanden ist, und auf deinen eigenen Zeitplan zurückfällt, wenn nicht.
OpenAIs Hinweise zu Wiederholungen, kurz gefasst:
- Behandle
Retry-Afterals die minimale Wartezeit und füge eine kleine zufällige Verzögerung hinzu. - Ohne ihn verwende exponentielles Backoff mit Jitter.
- Begrenze sowohl die Anzahl der Versuche als auch die gesamte Wiederholungszeit.
- Stapel deine eigenen Wiederholungen nicht auf die Wiederholungen des SDK.
- Wiederhole keine Quota- oder Abrechnungsfehler.
- Fehlgeschlagene Anfragen zählen weiterhin zum Limit pro Minute, also verschlimmert eine aggressive Schleife die Lage.
- Beim Streaming spiele eine Anfrage nicht erneut ab, nachdem du bereits Ausgabe daraus konsumiert hast.
Python: Backoff mit Jitter#
Das offizielle openai-Paket funktioniert mit jedem OpenAI-kompatiblen Endpoint. Schalte die eigenen Wiederholungen des SDK ab (max_retries=0), damit sie sich nicht mit deinen multiplizieren. Die ID des Modells stammt aus der CheapTokens-Dokumentation; IDs unterscheiden sich zwischen Anbietern.
import os
import random
import time
from openai import OpenAI, APIStatusError
client = OpenAI(
base_url="https://api.cheaptokens.dev/v1",
api_key=os.environ["CHEAPTOKENS_API_KEY"],
max_retries=0, # we retry ourselves
)
RETRYABLE = {429, 500, 502, 503, 504}
def chat_with_retry(model, messages, max_attempts=5, max_total=60.0):
started = time.monotonic()
for attempt in range(max_attempts):
try:
return client.chat.completions.create(model=model, messages=messages)
except APIStatusError as err:
last = attempt == max_attempts - 1
if err.status_code not in RETRYABLE or last:
raise
header = err.response.headers.get("retry-after")
if header and header.replace(".", "", 1).isdigit():
delay = float(header) + random.uniform(0, 1) # minimum wait + jitter
else:
delay = random.uniform(0, min(30.0, 2.0 ** attempt)) # full jitter
if time.monotonic() - started + delay > max_total:
raise
time.sleep(delay)Die Obergrenze der Verzögerung ohne Header wächst 1, 2, 4, 8 Sekunden (begrenzt auf 30), und random.uniform wählt einen zufälligen Wert darunter, damit nicht alle Worker gleichzeitig aufwachen. Retry-After kann auch ein HTTP-Datum sein; der obige Code behandelt die numerische Form und fällt andernfalls auf Backoff zurück.
JavaScript: dieselbe Schleife#
import OpenAI from "openai";
const client = new OpenAI({
baseURL: "https://api.cheaptokens.dev/v1",
apiKey: process.env.CHEAPTOKENS_API_KEY,
maxRetries: 0, // we retry ourselves
});
const RETRYABLE = new Set([429, 500, 502, 503, 504]);
const sleep = (ms) => new Promise((r) => setTimeout(r, ms));
export async function chatWithRetry(model, messages, maxAttempts = 5, maxTotalMs = 60000) {
const started = Date.now();
for (let attempt = 0; attempt < maxAttempts; attempt++) {
try {
return await client.chat.completions.create({ model, messages });
} catch (err) {
const last = attempt === maxAttempts - 1;
if (!RETRYABLE.has(err.status) || last) throw err;
const header = Number(err.headers?.get?.("retry-after"));
const delayMs = Number.isFinite(header) && header > 0
? header * 1000 + Math.random() * 1000 // minimum wait + jitter
: Math.random() * Math.min(30000, 2 ** attempt * 1000); // full jitter
if (Date.now() - started + delayMs > maxTotalMs) throw err;
await sleep(delayMs);
}
}
}Wenn es funktioniert, dauert ein rate-limitierter Aufruf einfach länger und gibt dann eine normale Completion zurück. Wenn er nach dem letzten Versuch immer noch fehlschlägt, wird der ursprüngliche Fehler ausgelöst, sodass dein Code ihn protokollieren oder den Job für später einreihen kann.
Wie Agenten mit 429 umgehen sollten#
Eine Agenten-Schleife sendet viele kurze Aufrufe, und mehrere Agenten oder Tool-Aufrufe können gleichzeitig laufen. Alleiniges Wiederholen reicht nicht; senke die Anfragefrequenz an der Quelle:
- Begrenze die Parallelität. Ein Semaphor von 3–5 parallelen Aufrufen ist ein sinnvoller Anfang; erhöhe ihn nur, solange Fehler selten bleiben.
- Teile einen Limiter. Wenn mehrere Worker denselben Schlüssel verwenden, teilen sie dieselben Limits, also reicht eine Retry-Schleife pro Worker nicht: Verwende eine Warteschlange oder ein Semaphor für den Prozess.
- Backoff global. Wenn ein Aufruf einen 429 mit einer Verzögerung erhält, pausiere den gesamten Pool für diese Zeit, nicht nur den fehlschlagenden Aufruf.
- Halte Anfragen kleiner. Weniger Tokens pro Anfrage bedeuten weniger Druck auf Tokens-pro-Minute-Limits: kürze Verlauf und Tool-Ausgabe. Siehe wie man die Kosten eines KI-Agenten schätzt, um zu erfahren, wohin die Tokens gehen.
- Stoppe bei nicht wiederholbaren Fehlern. Ein 401, 400 oder ein Guthabenfehler behebt sich nicht von selbst; scheitere schnell und melde.
import asyncio
limit = asyncio.Semaphore(4) # at most 4 requests in flight
async def run(job):
async with limit:
return await call_model(job) # your async call with the retry loop aboveAgenten-Schleifen auf CheapTokens ausführen#
Für Agenten-Schleifen mit vielen kurzen Aufrufen bietet CheapTokens MiniMax-M2.7: ein Preis zu jeder Tageszeit, ein 180K-Kontext, bis zu 8.192 Tokens pro Antwort und ein Guthaben für alle Modelle. Die Ausgabe kostet $0.15 pro 1M Tokens, und insgesamt, mit Eingabe und Ausgabe zusammen gezählt, ist es günstiger als OpenRouter. Es funktioniert über den OpenAI-kompatiblen Endpoint https:/. Der obige Code zeigt bereits auf diesen Endpoint; setze die Modell-ID aus der CheapTokens-Dokumentation und führe ihn aus.
Live-Preise für eine Arbeitslast von 500.000 Eingabe- und 100.000 Ausgabe-Tokens:
| Modell | Input $/1M | Output $/1M | Kosten | OpenRouter |
|---|---|---|---|---|
| GLM-5.3-Flash | $0.02 | $0.04 | $0.014 | $0.0282 |
| DeepSeek-V4-Flash | $0.015 | $0.10 | $0.0175 | $0.0394 |
| MiniMax-M2.7 | $0.05 | $0.15 | $0.04 | $0.27 |
500.000 Input- und 100.000 Output-Tokens insgesamt. Die Preise pro 1 Mio. Tokens sind aktuell und ändern sich zusammen mit unseren Tarifen; die OpenRouter-Spalte zeigt Referenzpreise für dieselbe Arbeitslast.
Siehe alle Preise, die Setup-Dokumentation, und erstelle einen Schlüssel, um deine erste Anfrage zu senden.
Wenn es immer noch fehlschlägt#
- 429 bei der allerersten Anfrage. Lies den Fehlertyp und die Meldung im Antwort-Body: Ein 429 wegen Ausgaben- oder Kontolimit schlägt bei Wiederholung weiter fehl, bis das Limit erhöht oder der Zugang wiederhergestellt ist, während ein Rate-Limit-429 nach einer Pause verschwindet.
- 429 kommt weiterhin mit einer langen Schleife. Möglicherweise stapelst du Wiederholungen: SDK-Wiederholungen mal deine Wiederholungen. Setze das SDK auf null, wie in den Beispielen.
- Fehler kommen am Anfang eines Batches in Schüben. Steigere dich allmählich, statt alle Worker auf einmal zu starten; OpenAI meldet
slow_downfür Traffic, der zu schnell wächst. - Streaming-Aufruf mittendrin fehlgeschlagen. Spiele ihn nicht blind erneut ab, nachdem du Ausgabe konsumiert hast; entscheide, ob du die ganze Antwort neu startest oder mit dem fortfährst, was du hast.
- Kein Retry-After in der Antwort. Der Code fällt auf Backoff mit Jitter zurück, also ist keine Änderung nötig.



