Caicaini
Начать

Справочник

Ошибки

Все ответы не из 2xx используют один конверт. HTTP-статус и поле error.type вместе говорят, что делать — повторить, отложить, починить вход или остановиться.

Конверт ошибки

Любой ответ с ошибкой — это JSON одной и той же формы. Верхний type всегда литеральная строка "error"; смысл — в error.type.

ответ с ошибкой
{
  "type": "error",
  "error": {
    "type": "invalid_request_error",
    "message": "max_tokens must be a positive integer."
  }
}

Коды статуса

HTTPtypeКогда возникает
400invalid_request_errorТело запроса невалидно или нарушает ограничение (неизвестная модель, слишком большой max_tokens, кривой массив messages). Не повторяй — чини вход.
401authentication_errorAPI-ключ отсутствует, искажён или невалиден. Не повторяй как есть — переаутентифицируйся.
402insufficient_quotaБаланс apiCredits ниже, чем нужно для этого поворота. Жёсткий стоп. Пополни на /developers/billing.
403permission_errorКлюч аутентифицирован, но не допущен на эту поверхность (CLI-ключ на /v1/*, аккаунт приостановлен, не совпадают скоупы).
404not_found_errorПуть или ресурс не существует. Проверь URL и id модели.
413request_too_largeТело превысило лимит запроса в 16 МБ. Раздроби payload или уменьши изображения.
429rate_limit_errorПоймал лимит per-key. Уважай Retry-After. Кредиты не списываются.
500api_errorВнутренний сбой у нас. Повтори с backoff. Идемпотентно.
502api_errorВышестоящий провайдер вернул ошибку. Повтори с backoff.
503api_errorСервис временно недоступен (деплой, обслуживание). Повтори с backoff.
504api_errorПровайдер вышел по таймауту. Повтори с backoff. Можно понизить max_tokens.
529overloaded_errorПерегрузка по мощности на вышестоящей модели. Повтори с backoff. Часто проходит за несколько секунд.

Как работать с каждым классом

  • Можно повторять: 429, 500, 502, 503, 504, 529. Экспоненциальный backoff с джиттером. Если есть Retry-After — уважай. Не больше 4–6 попыток.
  • Жёсткий стоп: 402 (insufficient_quota) и 401/403 (authentication_error, permission_error). Никакие ретраи не помогут. Эскалируй человеку или в алертинг.
  • Чинить вход: 400 (invalid_request_error) и 413. В следующий раз валидируй до отправки; правь вызывающую сторону.

Идентификаторы сообщений

Каждый успешный ответ несёт поле id (например, msg_01H8fkx2N3p4q5r6s7t8u9v0wx на /v1/messages, chatcmpl_... на /v1/chat/completions). Сохраняй id на каждом вызове. При обращении в поддержку id — самый быстрый способ для нас отследить весь жизненный цикл запроса: какой провайдер выбран, что было зарезервировано и что в итоге списано.

Маленький переиспользуемый обработчик

Заверни каждое место вызова в функцию, которая раскладывает ответ по трём ведёркам выше. Пример ниже отличает insufficient_quota (не повторяй) от rate_limit_error (повтори) и от транзиентных ошибок провайдера (повтори). Стратегию ретраев выбирает вызывающий.

# Inspect the type field to decide what to do.
status=$(curl -s -o /tmp/body -w "%{http_code}" \
  -X POST https://caicaini.com/v1/messages \
  -H "Authorization: Bearer cai_api_YOUR_KEY" \
  -H "Content-Type: application/json" \
  -d '{"model":"caicaini/auto","max_tokens":50,"messages":[{"role":"user","content":"Hi"}]}')

errtype=$(jq -r '.error.type // empty' /tmp/body 2>/dev/null)
echo "status=$status type=$errtype"

case "$status$errtype" in
  200*)                                  echo "ok" ;;
  402*|*insufficient_quota)              echo "top up at /developers/billing"; exit 2 ;;
  429*|*rate_limit_error)                echo "throttled — sleep, then retry" ;;
  500*|502*|503*|504*|529*)              echo "transient — retry with backoff" ;;
  *)                                     echo "fatal — fix the request"; exit 1 ;;
esac