502 upstream_unavailable и 503: как правильно ретраить
Ошибки 502 и 503 означают, что запрос не дошёл до модели по вине поставщика или маршрута, а не по вине вашего кода. go2llm возвращает 502 upstream_unavailable с сообщением all safe upstream attempts failed и 503 с кодами product_paused или no_eligible_route. Оба статуса безопасно ретраить — но только для текстовых запросов и только до первого байта SSE-стрима.
Страница составлена 2026-09-11, обновлена 2026-09-11.
Как выглядит ошибка
go2llm на исчерпании безопасных попыток к поставщикам отдаёт 502:
{
"error": {
"type": "upstream_unavailable",
"code": "upstream_unavailable",
"message": "all safe upstream attempts failed",
"request_id": "gw_5e0c92a1d7b3486fa4e18c05b2d7f639"
}
}
Второй вариант того же класса — когда маршрута нет вовсе, статус 503:
{
"error": {
"type": "upstream_unavailable",
"code": "upstream_unavailable",
"message": "no upstream route is currently available",
"request_id": "gw_af71b3e2c5d8420e93a6f10d7c4b2e58"
}
}
Третий вариант — маршрут есть, но ни один не проходит по условиям запроса: 503 с типом no_eligible_route и сообщением no qualified compatible route is available.
Четвёртый — плановая пауза продукта: 503 с типом product_paused, заголовок retry-after: 60.
Официальный Anthropic API в аналогичных ситуациях отвечает нестандартным статусом 529 с типом overloaded_error — это перегрузка на стороне Anthropic, и обрабатывать её нужно так же, как 503. OpenAI API отдаёт 503 service_unavailable.
Причины 502 и 503
1. Поставщик не ответил или ответил ошибкой на все безопасные попытки
go2llm держит несколько маршрутов к одной модели и до начала ответа может использовать совместимый fallback-маршрут на разрешённых классах ошибок. Сообщение all safe upstream attempts failed означает, что все такие попытки исчерпаны — то есть проблема шире одного поставщика.
2. Для модели нет доступного маршрута прямо сейчас
no upstream route is currently available — маршрут к запрошенной модели временно отсутствует. Проверка занимает один запрос без ключа: GET https://go2llm.tech/status.
3. Маршруты есть, но ни один не подходит под запрос
no_eligible_route возникает, когда доступные маршруты не удовлетворяют условиям запроса. Практический шаг — попробовать соседнюю модель того же протокола: claude-sonnet-5 вместо claude-opus-5 на POST /v1/messages, gpt-5.6-terra вместо gpt-6-astra на POST /v1/chat/completions.
4. Продукт на паузе
product_paused — go2llm сознательно приостановил обслуживание направления. Шлюз ставит retry-after: 60, то есть повтор имеет смысл не раньше чем через минуту.
5. Перегрузка у самого вендора
Anthropic API возвращает 529 overloaded_error в часы пиковой нагрузки. Это не ошибка вашего запроса и не ошибка шлюза; лечится ожиданием и, при затяжной перегрузке, переключением на другую модель.
6. Клиентский таймаут короче времени генерации
Ответ на 4000 выходных токенов у крупной модели может занимать десятки секунд. Таймаут HTTP-клиента в 10 секунд разрывает соединение, и приложение видит сетевую ошибку, внешне похожую на 502, хотя go2llm запрос обрабатывал. Ставьте таймаут не меньше 120 секунд для нестримовых запросов.
Как починить по шагам
Шаг 1. Посмотрите GET https://go2llm.tech/status — endpoint работает без ключа и показывает состояние шлюза.
Шаг 2. Определите, можно ли ретраить. Безопасно повторять: текстовые запросы к POST /v1/messages и POST /v1/chat/completions на 429, 502, 503 и сетевых таймаутах. Нельзя повторять автоматически: media-запрос, вернувший ambiguous_upstream_result, — поставщик мог его принять, и повтор спишет деньги дважды. Нельзя повторять SSE-стрим после первого валидного события — go2llm не переключает маршрут после первого байта, а клиентский ретрай даст дублирующий ответ.
Шаг 3. Внедрите backoff с jitter и потолком. Рабочая реализация под коды go2llm:
import random, time
import httpx
RETRYABLE_STATUS = {429, 502, 503, 529} # 529 — overloaded_error у Anthropic
NEVER_RETRY_CODES = {"quota", "ambiguous_upstream_result"}
def call_text(payload, api_key, *, max_attempts=6, base=1.0, cap=32.0, timeout=120.0):
"""Повтор текстового запроса к go2llm на 429/502/503 с экспоненциальным backoff."""
last = None
with httpx.Client(timeout=timeout) as client:
for attempt in range(max_attempts):
try:
r = client.post(
"https://go2llm.tech/v1/chat/completions",
headers={"Authorization": f"Bearer {api_key}"},
json=payload,
)
except (httpx.TimeoutException, httpx.TransportError) as exc:
last, status, code, msg = exc, None, "network", str(exc)
else:
if r.status_code < 400:
return r.json()
err = r.json().get("error", {})
if not isinstance(err, dict):
err = {"message": str(err)}
status = r.status_code
code = err.get("code") or err.get("type")
msg = err.get("message")
last = RuntimeError(
f"{status} {code}: {msg} [request_id={err.get('request_id')}]"
)
if code in NEVER_RETRY_CODES or status not in RETRYABLE_STATUS:
raise last
hint = r.headers.get("retry-after")
if hint and hint.isdigit():
time.sleep(float(hint) * (0.5 + random.random() / 2))
continue
if attempt == max_attempts - 1:
raise last if isinstance(last, Exception) else RuntimeError(msg)
delay = min(cap, base * 2 ** attempt)
time.sleep(delay * (0.5 + random.random() / 2)) # jitter 50–100%
Шесть попыток с базой 1 секунда и потолком 32 секунды дают до ~47 секунд суммарного ожидания. Для фоновых задач поднимайте max_attempts до 8 и cap до 60 секунд, для интерактивных — опускайте до 3 попыток и cap 8 секунд.
Шаг 4. Если 502 повторяется больше пяти минут — отправьте error.request_id (он начинается с gw_) в support@go2llm.tech или Telegram @go2llm_support. Request logs go2llm хранятся до 90 дней и содержат маршрут, usage, стоимость, статус и очищенную ошибку; промпты и ответы в продуктовые логи не пишутся.
Как избежать 502 и 503 в будущем
Держите fallback-модель того же протокола и переключайтесь на неё после второго 502 подряд. На POST /v1/messages парой идут claude-opus-5 ($0.50 / $2.51 / $0.05 за 1M) и claude-sonnet-5 ($0.33 / $1.64 / $0.033) — код не меняется, меняется строка модели. На POST /v1/chat/completions — gpt-6-astra и gpt-5.6-sol ($0.40 / $2.01 / $0.04).
Разделяйте таймауты: 120 секунд на нестримовый запрос и отдельный, более длинный, на стрим. Слишком короткий таймаут создаёт ложные 502 в ваших метриках и мешает отличить проблему поставщика от проблемы клиента.
Не ретрайте всё подряд. 400, 401, 402, 403, 404 и 409 при повторе вернут тот же ответ, а лимит 20 RPM на ключ израсходуется впустую. Ветвитесь по error.code, а не по HTTP-статусу: под одним 429 у go2llm живут ретраибельный rate_limit и неретраибельный quota.
Считайте деньги: неудачный запрос к go2llm не списывает ничего — шлюз резервирует оценку до вызова и освобождает резерв, баланс не уходит ниже нуля. Стоимость успешного запроса приходит в usage.cost_usd, в том числе в финальном usage-блоке SSE.
Связанные ошибки
- 429 rate_limit_error — тот же backoff, другая причина.
- 404 model_not_found — модель не в каталоге, ретрай бесполезен.
- 402 insufficient_balance — не хватает средств.
- Справочник всех кодов и docs/errors.
FAQ
Чем 502 отличается от 503 в go2llm? 502 upstream_unavailable с сообщением all safe upstream attempts failed означает, что попытки к поставщикам были и все провалились. 503 означает, что подходящего маршрута не нашлось вовсе: no upstream route is currently available, no_eligible_route или плановая пауза product_paused с заголовком retry-after: 60.
Можно ли повторить оборвавшийся SSE-стрим? Нет, если уже получено хотя бы одно валидное SSE-событие. go2llm может подобрать совместимый fallback-маршрут только до первого байта ответа; после этого переключение не выполняется, и повтор на клиенте даст дублирующую генерацию и второе списание.
Что делать с ambiguous_upstream_result? Не повторять автоматически. Этот результат означает, что поставщик мог принять media-запрос, и автоматический ретрай приведёт к двойной оплате. Проверьте результат вручную и при необходимости отправьте новый запрос с новым Idempotency-Key.
Anthropic возвращает 529 — это ошибка go2llm? Нет. Статус 529 overloaded_error — нестандартный код самого Anthropic API, означающий перегрузку на их стороне. Обрабатывайте его в той же ветке, что 503: экспоненциальный backoff с jitter, при затяжной перегрузке — переключение на другую модель.
Получить ключ и сделать первый запрос за 3 минуты → go2llm.tech. Состояние шлюза — GET /status, подключение — в документации, цены — на странице тарифов.