Strona główna → Pomoc

429 z bramki API oznacza dwie różne rzeczy

Czytaj treść odpowiedzi, nie kod statusu. 429 z powodu pustego salda nigdy nie uda się przy ponowieniu, niezależnie od tego, jak długo odczekasz. 429 z powodu przeciążenia upstreamu zwykle mija w kilka sekund.

Co widzisz

Dlaczego tak się dzieje

HTTP nie ma statusu oznaczającego „skończyły ci się pieniądze”. 402 Payment Required istnieje, ale prawie nikt go nie używa, więc bramki używają 429 zarówno do rozliczeń, jak i do ograniczania ruchu. W praktyce to przeciwieństwa: jedno trwa, dopóki czegoś nie zrobisz, drugie jest chwilowe i mija samo.

To ważne, bo większość mechanizmów ponawiania w SDK patrzy tylko na kod statusu. Klient OpenAI dla Pythona domyślnie ponawia 429. Skieruj go na bramkę z pustym saldem, a wypali cały budżet ponowień na zapytaniu, które nie może się udać, i na koniec zgłosi timeout – a ty zaczniesz szukać problemu z siecią, którego nie ma.

Jest też trzecia przyczyna, którą warto znać, bo wygląda jak druga, a naprawia się ją inaczej: limit równoległych zapytań na konto. Komunikat mówi o nim wprost — Concurrency limit exceeded for user, please retry later. Tu nie chodzi o to, ile zapytań wysłałeś w ciągu minuty, tylko ile było w toku w tej samej chwili. Odczekanie pomaga, ale właściwym rozwiązaniem jest ograniczenie równoległości w kliencie; to jej zwiększenie wywołało błąd.

Sprawdź, czy to ta przyczyna

Wyślij jedno zapytanie i spójrz na treść zamiast na status:

curl -s -o /tmp/r.json -w '%{http_code}\n' \
  'YOUR_BASE_URL/chat/completions' \
  -H 'Authorization: Bearer YOUR_KEY' \
  -H 'Content-Type: application/json' \
  -d '{"model":"YOUR_MODEL","messages":[{"role":"user","content":"hi"}],"max_tokens":1}'

cat /tmp/r.json

Kod lub komunikat ze słowami quota, balance albo credit oznacza rozliczenia. Wszystko ze słowami rate, busy albo upstream oznacza ograniczenie ruchu. Jeśli treść jest pusta, sprawdź nagłówek Retry-After – jego obecność wskazuje na ograniczenie ruchu.

Jak to naprawić

  1. Przed ponowieniem rozgałęź logikę według treściSparsuj JSON-a i traktuj 429 związane z rozliczeniami jako błąd ostateczny. Ponawianie ich marnuje budżet ponowień i ukrywa prawdziwą przyczynę za timeoutem.
  2. Respektuj Retry-After, jeśli jestOdpowiedzi o ograniczeniu ruchu często go zawierają. Gdy go brak, rozsądnym domyślnym wyborem jest wykładnicze wycofanie zaczynające się od około sekundy; natychmiastowe ponawianie zwykle pogarsza przeciążenie.
  3. Monitoruj saldo osobno od błędówPuste saldo to zdarzenie biznesowe, a nie awaria. Większość bramek pokazuje saldo przez własne API lub panel – obserwuj tę liczbę, a nigdy nie spotkasz tego 429 na produkcji.
  4. Ograniczaj zapytania w toku, a nie tylko tempoJeśli komunikat wspomina o równoległości, wolniejsza pętla ponowień nie pomoże — limit liczy zapytania jednoczesne. Semafor wokół klienta, ustawiony na tyle, ile pozwala bramka, rozwiązuje to porządnie.
  5. Nie zwiększaj równoległości, żeby naprawić 429 z ograniczenia ruchuWięcej równoległych zapytań do przeciążonego upstreamu daje więcej 429, a nie większą przepustowość. Zmniejsz równoległość i pozwól działać wycofywaniu.
W APICLAN oba przypadki da się odróżnić bez zgadywania. Puste saldo zwraca {"code":"API_KEY_QUOTA_EXHAUSTED"}; przeciążenie upstreamu zwraca {"error":{"type":"api_error","message":"Upstream rate limit exceeded, please retry later"}}. Saldo widzisz w panelu, a doładowania działają od razu.

Powiązane

Unexpected token '<' przy wywołaniu API zgodnego z OpenAI401 invalid API key – gdy klucz wygląda dobrze, a i tak nie działa

Ostatnio sprawdzono 2026-10-01. Napisane na podstawie problemów zdiagnozowanych na działającej bramce zgodnej z OpenAI, a nie zebrane z innych stron.