Ошибки AI API: что делать с 401, 402, 429 и 503
Статус ошибки — это инструкция, а не приговор. 401 чинится ключом, 402 — деньгами, 429 — паузой, 503 — ожиданием. Статья — про то, как не перепутать ветки и не заплатить за повторы дважды.
Классификация за секунду
Все ошибки делятся на два семейства. 4xx — это вы: неверный ключ, кривой запрос, пустой баланс. 5xx и сетевые обрывы — это они: провайдер, маршрут, сеть. Семейство определяет всё дальнейшее.
Золотое правило: постоянные ошибки чинятся руками, временные — повтором с дедлайном. Перепутанные ветки либо плодят бессмысленную нагрузку, либо роняют то, что само бы прошло.
- первая цифра статуса решает: 4xx — чинить запрос, 5xx — ждать и повторять
- повтор допустим только для временных состояний
- каждая ветка — своё действие в UI
401, 403, 402: чинить, не повторять
401 означает отсутствующий, неверный или отозванный ключ. 403 — ключ в порядке, но ему нельзя: чужой scope, неразрешённая модель, неподдержанный endpoint. 402 — деньги: пустой баланс или достигнутый лимит.
Повтор одного и того же запроса эти состояния не исправит — он только засорит журнал. Покажите пользователю действие: проверить ключ, пополнить баланс, выбрать разрешённую модель.
- 401 — проверить Authorization и статус ключа
- 403 — scope, модель, endpoint
- 402 — баланс и budget limit
- 400 — тело запроса
429: бюджет или частота
Один статус — две разные причины. budget_exceeded: ключ упёрся в лимит расходов, повтор бессмысленен, лимит меняется в кабинете. rate_limit_exceeded: слишком частые запросы — уважайте Retry-After и повторяйте с экспоненциальной задержкой.
Интерактивному UI чаще лучше быстро показать «проверьте баланс» или «попробуйте позже», чем держать пользователя в молчаливой очереди.
- budget_exceeded — в кабинет за лимитом
- rate_limit_exceeded — backoff и Retry-After
- пользователю — понятное действие, а не тишина
503 и неизвестный результат
503 — провайдер или маршрут временно недоступны. Самый опасный подвид — обрыв после отправки запроса upstream: операция могла выполниться, а ответа вы не получили. Слепой повтор превращает один платный запрос в два.
Для неидемпотентных действий сначала проверьте состояние через журнал по X-Request-Id исходной попытки. Нет подтверждения — считайте результат неизвестным, а не проваленным.
Повторы с дедлайном
Без дедлайна повтор — это бесконечный цикл за ваши деньги. Зафиксируйте суммарное время ожидания и число попыток до первой попытки, а не когда очередь уже горит.
После восстановления не возвращайте автоматические повторы сразу: сначала проверьте лимиты и очередь. Классика жанра — новая волна нагрузки из собственных ретраев поверх только что ожившего провайдера.
- экспоненциальная задержка с джиттером
- жёсткий дедлайн и лимит попыток
- после восстановления — сначала лимиты, потом повторы
Диагностика через request ID
Минимальный набор для разбора: время, endpoint, model ID, статус, error code и X-Request-Id. Этого хватает, чтобы найти попытку в журнале, не передавая поддержке ключ или полный prompt.
Логируйте событие, а не секрет: Authorization, промпты и ответы в обычный application log не пишутся без отдельной причины и срока хранения.
- время, endpoint, model ID
- HTTP-статус, error code
- X-Request-Id каждой попытки
Открыть эту статью в Markdown·Поделиться в Telegram
Следующий материалStreaming ответов AI через SSE: практическое руководство