У ошибок GLM API два уровня: внешний — HTTP-код состояния, внутренний — бизнес-код в теле ответа. По внешнему уровню легко ошибиться: например, задолженность по аккаунту тоже возвращается как 429. Порядок диагностики такой: сначала прочитать бизнес-код и сообщение об ошибке, затем найти request ID или error ID, воспроизвести минимальным запросом и только потом менять параметры или модель.

Ниже разобраны 401, 403, 404, 429, 5xx и тайм-ауты: таблица бизнес-кодов, код обработки ошибок и чек-лист перед обращением в поддержку. Модели и цены — на странице цены на модели.

Примечание: Zhipu, GLM и BigModel — товарные знаки соответствующих правообладателей. Статья носит технический характер и не подразумевает аффилированность, агентские или лицензионные отношения с Zhipu. Коды ошибок, правила лимитирования и поведение интерфейсов могут меняться; окончательно ориентируйтесь на официальную документацию и фактический ответ.

1. Сначала различите два уровня ошибок

HTTP-код описывает результат на уровне протокола, бизнес-код — конкретную причину. Один и тот же 401 может означать отсутствие заголовка аутентификации, истёкший токен или вторую аутентификацию; один и тот же 429 — лимит скорости, занятость модели, задолженность или потолок тарифа. Записывать бизнес-код в журнал — самый эффективный шаг диагностики.

HTTP Частые бизнес-коды Значение Уместен ли повтор
401 1000 / 1001 / 1003 / 1005 Сбой аутентификации, нет заголовка, токен истёк, вторая аутентификация Нет, сначала исправить учётные данные
403 1220 Нет доступа к этому API или модели Нет, проверить тариф и права
400 1210 / 1211 / 1221 / 1222 / 1261 Ошибка параметров, модель не существует, API снят или отсутствует, слишком длинный Prompt Нет, изменить запрос
429 1113 Задолженность по аккаунту Нет, сначала пополнить
429 1302 / 1305 Ограничение скорости, слишком высокая нагрузка на модель Да, повторить с задержкой
429 1308 / 1310 Периодический потолок, сброс по next_flush_time Ждать сброса, не повторять настойчиво
429 1311 / 1313 / 1315 В тарифе нет модели, ограничение добросовестного использования, несовпадение типа ключа Нет, проверить тариф и ключ
500 1200 / 1230 / 1234 Внутренняя ошибка, сбой процесса, сетевая ошибка (с error ID) Да, с задержкой и сохранением error ID

В таблице самые частые соответствия; полный список — в официальной документации. При обрыве потока бизнес-кода может не быть: причина видна в finish_reason или последнем фрагменте данных.

2. 401: четыре вида сбоя аутентификации

401 означает, что личность не подтверждена; к возможностям модели и балансу это обычно отношения не имеет. Официальные коды довольно подробно разделяют причины:

  • 1000 — сбой аутентификации: неверный ключ, неполное копирование или ключ удалён.
  • 1001 — в заголовке нет параметра аутентификации: отсутствует Authorization: Bearer <key> или его отбросил прокси.
  • 1003 — токен истёк: у ключа есть срок или его ротировали в консоли.
  • 1005 — включена вторая аутентификация: пройдите проверку по требованиям платформы.

Проверяйте по порядку:

  1. Формат заголовка: один пробел после двоеточия, вокруг ключа нет кавычек и переводов строки.
  2. Выведите префикс переменной окружения и убедитесь, что там не пусто и не старое значение.
  3. Уточните тип ключа: ключи стандартного API, Coding Plan, командные и корпоративные ведутся раздельно и не смешиваются.
  4. Убедитесь, что Base URL соответствует владельцу ключа: официальный ключ — официальный адрес, ключ шлюза — адрес шлюза.
  5. Создайте новый ключ и повторите минимальный запрос, чтобы отделить проблему ключа от настройки прокси или шлюза.

При копировании ключа из окна чата чаще всего появляются пробелы или переводы строки. Запрос, который выводит одно слово, отсекает большинство простых ошибок.

3. 403 и 404: права, путь и имя модели

Частый бизнес-код 403 — 1220: у текущего аккаунта нет доступа к этому API или модели. Проверьте, входит ли модель в тариф, относится ли ключ к нужному типу продукта, не вызывается ли неподключённый интерфейс. Повторы здесь бесполезны: меняйте права или ключ.

404 чаще означает не «сервис упал», а неверный адрес: в Base URL лишний или пропущенный /v1; SDK сам добавляет путь, а в коде он указан ещё раз; правило перезаписи обратного прокси испортило путь. Неверное имя модели GLM обычно возвращает 400 с кодом 1211, а снятый или отсутствующий API — 1221 и 1222. Поэтому при 404 сначала проверяйте адрес, при 1211 — имя модели.

Имя модели берите из официальной документации и страницы цен, не пишите версию по памяти. При обновлении модели сначала проверьте совместимость параметров в тестовой среде.

4. 429: сначала прочитайте бизнес-код, потом решайте о повторе

429 обрабатывают неправильно чаще всего. Он включает как минимум пять ситуаций:

  • 1113 — задолженность по аккаунту: повторять до пополнения бессмысленно.
  • 1302 — достигнут предел скорости: снизьте параллелизм или сделайте задержку.
  • 1305 — слишком высокая текущая нагрузка на модель: обычно связано с пиком; повторите с задержкой, при необходимости переключите резервную модель.
  • 1308, 1310 — достигнут периодический лимит: в сообщении есть время сброса, дождитесь восстановления квоты.
  • 1309, 1311, 1313, 1315 — истёк тариф, модель не открыта, ограничение добросовестного использования или несовпадение типа ключа: поможет только изменение конфигурации.

Автоматический повтор уместен только для кратковременных лимитов вроде 1302 и 1305; в остальных случаях он лишь удлиняет простой. Правила лимитирования (параллелизм, запросы в минуту или скорость токенов) зависят от тарифа и модели; ориентируйтесь на консоль и официальную документацию.

5. 5xx и тайм-ауты: локализуйте отдельно

Серия 500 включает 1200 (внутренняя ошибка), 1230 (сбой процесса) и 1234 (сетевая ошибка). У 1234 обычно есть error ID — обязательно сохраните его для поддержки. При устойчивых 5xx сначала сделайте задержку, затем проверьте статус сервиса или уведомления провайдера; не повторяйте с высокой частотой.

Тайм-аут нужно смотреть в трёх разрезах: тайм-аут соединения означает недоступность DNS, выхода или прокси; медленный первый токен — обычно очередь у провайдера или слишком длинный вход; тайм-аут чтения — слишком длинный вывод или долгие рассуждения. Обработка различается, поэтому недостаточно просто увеличить общий тайм-аут.

При обрыве потокового запроса может не быть ни HTTP-кода, ни бизнес-кода. Сохраните принятое содержимое и последний фрагмент, проверьте finish_reason и определите, это сетевая нестабильность, обрыв прокси или тайм-аут провайдера. Не записывайте половину ответа в базу как полный результат.

6. Request ID и журналы: доказательства для диагностики

Официальный ответ не обязательно содержит request ID с одинаковым именем во всех интерфейсах; имена полей смотрите в фактическом ответе и документации. Надёжнее вести двойную запись: клиент генерирует trace_id, который проходит через все повторы, а тело ошибки провайдера и любые поля request id или error id сохраняются как есть.

Журнал должен содержать как минимум: время, trace_id, Base URL, имя модели, HTTP-код, бизнес-код, сообщение об ошибке, длительность, число повторов и признак потокового режима. Ключ записывайте только частично или в виде хэша; исходный текст пользователя и полный ответ не сохраняйте целиком.

Эти поля нужны не только вам. При обращении в поддержку запись с trace_id, бизнес-кодом и минимальным воспроизведением гораздо полезнее фразы «иногда падает».

7. Повторы и задержка: пример кода

Код ниже отключает автоповторы SDK, решает о повторе по бизнес-коду и печатает trace_id, код состояния и бизнес-код. Сетевые тайм-ауты обрабатываются отдельно, число повторов ограничено.

import os
import random
import time
import uuid

import httpx
from openai import OpenAI, APIConnectionError, APIStatusError, APITimeoutError

client = OpenAI(
    api_key=os.environ["GLM_API_KEY"],
    base_url=os.environ.get(
        "GLM_BASE_URL", "https://open.bigmodel.cn/api/paas/v4"
    ),
    timeout=httpx.Timeout(connect=5.0, read=120.0, write=30.0, pool=10.0),
    max_retries=0,  # автоповторы SDK отключены, логику задаёт код ниже
)

RETRYABLE_CODES = {1302, 1305}  # лимит скорости и занятость модели; задолженность и потолок тарифа сюда не входят

def ask(prompt: str, max_attempts: int = 4) -> str:
    trace_id = uuid.uuid4().hex[:12]
    for attempt in range(1, max_attempts + 1):
        try:
            resp = client.chat.completions.create(
                model=os.environ["GLM_MODEL"],
                messages=[{"role": "user", "content": prompt}],
                max_tokens=1024,
            )
            return resp.choices[0].message.content
        except APIStatusError as exc:
            code = None
            try:
                code = int(exc.response.json().get("code"))
            except Exception:
                pass
            print(
                f"trace={trace_id} attempt={attempt} "
                f"http={exc.status_code} code={code} "
                f"body={exc.response.text[:500]}"
            )
            retryable = exc.status_code >= 500 or (
                exc.status_code == 429 and code in RETRYABLE_CODES
            )
            if not retryable or attempt == max_attempts:
                raise
        except (APITimeoutError, APIConnectionError) as exc:
            print(f"trace={trace_id} attempt={attempt} err={type(exc).__name__}")
            if attempt == max_attempts:
                raise
        wait = min(2 ** (attempt - 1), 20) + random.uniform(0, 1)
        time.sleep(wait)
    raise RuntimeError("Попытки исчерпаны")

Три дополнительных правила: по возможности соблюдайте Retry-After из ответа сервера; контролируйте бюджет повторов глобально, чтобы несколько сервисов не суммировали попытки; для запросов с побочными эффектами сначала подтверждайте состояние по идемпотентному ключу, потом решайте о повторной отправке.

8. Управление параллелизмом: эффективнее увеличения числа повторов

Проблему лимитов обычно решает не повтор, а управление входом:

  • Каждому сервису — отдельный ключ и собственный предел параллелизма.
  • Пакетные задачи дробите на части и смещайте по времени, избегая пика в начале часа.
  • Сглаживайте пики очередью: неудачные задачи отправляйте в очередь отложенной обработки, а не крутите на месте.
  • Следите за долей 429 и P95 задержки; при резком росте сначала снижайте параллелизм.
  • Подготовьте резервную модель или вход, но перед переключением проверьте совместимость параметров.

Конкретные значения параллелизма, запросов в минуту и скорости токенов зависят от тарифа и модели; ориентируйтесь на консоль и официальную документацию. Не копируйте чужие цифры — ставьте по своим измерениям.

9. Чек-лист перед обращением в поддержку

  1. Время и часовой пояс; носит ли сбой массовый характер.
  2. Base URL, путь интерфейса, имя модели и метод запроса.
  3. HTTP-код, бизнес-код и полный текст ошибки.
  4. Error ID или request ID; если их нет — свой trace_id.
  5. Минимальный воспроизводимый curl-запрос с обезличенным ключом.
  6. Был ли режим потоковым, длинный ли контекст, не менялась ли конфигурация.
  7. Зона влияния: один ключ, один проект или все сервисы.

С этими данными поддержка локализует проблему сразу, а не будет запрашивать информацию по кругу. После каждого инцидента добавляйте мониторинг и оповещения, не ждите жалоб пользователей.

10. Частые вопросы (FAQ)

1. 429 — это всегда ограничение скорости?

Нет. 429 может означать задолженность (1113), периодический потолок (1308, 1310), отсутствие модели в тарифе (1311) или ограничение добросовестного использования (1313). Сначала прочитайте бизнес-код, затем решайте: задержка, пополнение или изменение конфигурации.

2. 401 сохраняется даже с новым ключом. Что делать?

Проверьте, что заголовок имеет вид Authorization: Bearer <key>, переменная окружения загружена, тип ключа соответствует интерфейсу, Base URL и ключ относятся к одной платформе, а обратный прокси не отбрасывает заголовок аутентификации.

3. Нужно ли повторять запрос при тайм-ауте?

Только для сбоя соединения и тайм-аута чтения, с ограниченным числом попыток и экспоненциальной задержкой. В операциях с побочными эффектами сначала проверьте, выполнялась ли операция, чтобы не создать повторный заказ или запись.

4. Как диагностировать обрыв потокового вывода?

Сохраните принятое содержимое, последний фрагмент и finish_reason, затем отличите сетевую нестабильность, обрыв прокси и тайм-аут провайдера. Клиент должен поддерживать переподключение и дедупликацию; не записывайте половину ответа в базу.

5. В ошибке только код состояния, без бизнес-кода. Что делать?

Сохраните полное тело и заголовки ответа, зафиксируйте trace_id, Base URL, имя модели и минимальное воспроизведение, затем обратитесь к провайдеру. При работе через шлюз передайте эти данные шлюзу, чтобы он сопоставил их с журналами провайдера.

Что дальше

Создайте тестовый ключ в ZSQH AI Gateway, по одному разу отработайте 401, 403, 429, 5xx и тайм-аут, а затем подключите производственный мониторинг. Доступные модели и правила тарификации — на странице цены на модели.

Читайте также