# Лимиты, очереди и паузы

Подробный разбор кодов, которыми API Вайбкод отвечает при ограничении частоты запросов, переполненной очереди портала и паузах на стороне Битрикс24.

Сводная таблица всех кодов API Вайбкод — [Коды ошибок](/docs/errors).

## `RATE_LIMITED` (429)

Сработало одно из ограничений частоты: граница платформы Вайбкод, собственный лимит эндпоинта или лимит на стороне Битрикс24.

```json
{
  "success": false,
  "error": {
    "code": "RATE_LIMITED",
    "message": "QUERY_LIMIT_EXCEEDED",
    "hint": "Wait 1-2 seconds and retry. Use POST /v1/batch to combine up to 50 calls in 1 request."
  }
}
```

**Заголовки ответа:**

```
Retry-After: 2
```

Поля `retryAfter` в теле этого отказа нет — срок повтора приходит только заголовком. Поле `hint` приходит не на всех путях отказа: у границы платформы тело состоит из `code` и `message`.

**Причины:**
- Всплеск запросов с одного адреса превысил границу платформы — 60 запросов в секунду, считается по IP-адресу клиента. Такой отказ приходит с `Retry-After: 1` и без заголовков `X-RateLimit-*`. У части эндпоинтов на границе действует свой, более строгий лимит.
- Исчерпан собственный поминутный лимит эндпоинта. Он считается по API-ключу. Исключение — [`POST /v1/search`](/docs/search/run) (60 в минуту), [`POST /v1/batch`](/docs/batch) (30 в минуту) и [`POST /v1/research`](/docs/search/research) (20 в минуту): там счётчик один на портал, и все его ключи делят его между собой.
- Превышен лимит запросов в секунду на стороне Битрикс24. Он считается на портал.

**Решение:**
- Дождаться времени из заголовка `Retry-After`.
- Реализовать повторные попытки с экспоненциальной задержкой.
- Объединять до 50 вызовов через [`POST /v1/batch`](/docs/batch).
- Кэшировать справочные данные — поля, статусы, валюты.

---

## `ERROR_LOOP_DETECTED` (429)

Вайбкод фиксирует серию одинаковых ошибок на одном ключе для одного метода Битрикс24 — и временно блокирует запрос на стороне Вайбкод, чтобы не накручивать счётчики Битрикс24. Каждый N-й запрос пробрасывается дальше: если бэкенд восстановился, блокировка снимается автоматически.

```json
{
  "success": false,
  "error": {
    "code": "ERROR_LOOP_DETECTED",
    "message": "Vibe-side block (not a Bitrix24 limit). 12 failures on crm.deal.list in the last hour.",
    "hint": "Every 50th request will probe for recovery — keep retrying with backoff. If you suspect a platform-side issue (e.g. 5xx during an outage), platform admin can clear the block via POST /api/platform/analytics/circuit-breaker/<apiKeyId>/clear."
  }
}
```

**Заголовки ответа:**

```
Retry-After: 60
```

Поля `retryAfter` в теле этого отказа нет — срок повтора приходит только заголовком.

**Причины:**
- В коде клиента баг: запрос с одинаковыми параметрами повторяется и стабильно даёт ошибку.
- Платформенная авария на стороне Битрикс24 в момент серии запросов.

**Решение:**
- Прочитать `message` — там указан конкретный метод с серией ошибок.
- Найти источник запроса в коде, исправить параметры или логику.
- При платформенной аварии — повторять с задержкой: каждый N-й запрос платформа пропускает для проверки восстановления, и блокировка снимается сама. Если она держится дольше самой аварии, обратитесь в поддержку.
- Маршрут, названный в поле `hint` ответа, — служебный эндпоинт платформы. Своим ключом его не вызвать, и вмешательство не требуется: он адресован поддержке.

---

## `QUEUE_OVERFLOW` (429)

Очередь запросов к Битрикс24 для конкретного портала переполнена: слишком много вызовов уже в ожидании (по умолчанию — 100 и больше). Ответ возвращается мгновенно, за миллисекунды, с HTTP-заголовком `Retry-After: N` (секунды).

```json
{
  "success": false,
  "error": {
    "code": "QUEUE_OVERFLOW",
    "message": "Portal queue overloaded — 100 Bitrix24 calls already pending",
    "userMessage": "Слишком много одновременных запросов к Bitrix24 — повторите через несколько секунд.",
    "hint": "Honor the Retry-After header. Use exponential backoff with jitter for repeated failures.",
    "retryAfter": 10
  }
}
```

**Решение:**
- Повторить запрос через `Retry-After` секунд, увеличивая паузу перед каждой следующей попыткой и добавляя к ней случайную величину, чтобы повторы от разных клиентов не пришли одной волной.
- Уменьшить параллелизм на стороне клиента.
- Объединить вызовы через `POST /v1/batch`.

---

## `QUEUE_TIMEOUT` (429)

Очередь запросов к Битрикс24 для конкретного портала перегружена: больше 30 секунд ожидания.

```json
{
  "success": false,
  "error": {
    "code": "QUEUE_TIMEOUT",
    "message": "Portal queue saturated — too many concurrent Bitrix24 calls",
    "userMessage": "Запросы к Bitrix24 в очереди дольше 30 секунд. Вероятно, на портале много одновременных операций.",
    "hint": "The request was NOT sent to Bitrix24 — safe to retry (honor Retry-After, use backoff with jitter). If this is a /search request with a wide date range, try adding \"autoWindow\": false OR narrow the date range to <14 days.",
    "retryAfter": 10
  }
}
```

Запрос НЕ был отправлен в Битрикс24 — безопасно повторить.

**Решение:**
- Повторить через `retryAfter` секунд, увеличивая паузу перед каждой следующей попыткой и добавляя к ней случайную величину.
- Уменьшить параллелизм.
- Для `/search`-эндпоинтов — сузить диапазон дат либо передать `autoWindow: false`.
- Объединить вызовы через `POST /v1/batch`.
- Проверить таймаут на своей стороне: ожидание в очереди входит во время ответа, поэтому клиенту нужен запас — [Клиентский таймаут](/docs/optimization#клиентский-таймаут).

---

## `TIMEOUT_QUARANTINE` (429)

Метод несколько раз подряд не ответил вашему порталу Битрикс24 за отведённое вызову время, поэтому Вайбкод поставил пару «портал + метод» на паузу и больше не отправляет к ней запросы.

> **В процессе раскатки.** Механизм включается на порталах постепенно. Пока он не включён на вашем, этот код не приходит: вызовы уходят в Битрикс24 как раньше и упираются в таймаут [`BITRIX_TIMEOUT`](/docs/errors/platform#bitrix_timeout-503).

```json
{
  "success": false,
  "error": {
    "code": "TIMEOUT_QUARANTINE",
    "message": "Vibe-side block (not a Bitrix24 limit). crm.item.list timed out 5 times in a row on this portal, so calls to it are paused.",
    "hint": "Портал не отвечал на этот метод за отведённое вызову время, поэтому каждый следующий вызов только добавлял бы нагрузку. Дождитесь срока из Retry-After и НЕ сокращайте интервал повторов: агрессивный повтор занимает слот пробы восстановления и держит метод закрытым для всего портала дольше. Раз в 5 мин один вызов пропускается как проба, и первый успешный ответ снимает паузу немедленно. Облегчите запрос — меньше полей, меньше страница, более узкий фильтр: пару снимает с паузы именно лёгкий вызов.",
    "retryAfter": 288,
    "scope": "portal"
  }
}
```

**Заголовки ответа:**

```
Retry-After: 288
```

**Причины:**
- Метод стабильно не отвечает порталу за отведённое вызову время. Причина — тяжёлый запрос: широкий диапазон дат, много полей в `select`, большая страница, фильтр по неиндексированному полю.
- Пауза считается на пару «портал + метод» и не зависит от того, каким ключом сделан вызов: `scope: "portal"` означает, что её видят ВСЕ ключи портала, включая чужие интеграции. Контраст — [`OPERATION_TIME_LIMIT`](#operation_time_limit-429) со `scope: "apiKey"`: тот отказ про ваш ключ, этот — про весь портал.
- Это отказ на стороне Вайбкод, а не лимит Битрикс24: запрос до портала не дошёл, поэтому ничего не изменилось — повтор безопасен даже для методов записи.
- Код приходит и внутри `200`-ответа — на подвызовах [`POST /v1/batch`](/docs/batch), которые Вайбкод исполняет отдельными запросами (`data.errors[<id>]`), и на элементах батча одной сущности (`data[i].error`). У `200`-конверта нет заголовка `Retry-After` для отдельного подвызова, поэтому срок приходит полем `retryAfter`, а `scope` и `hint` — те же, что в одиночном `429`.

**Решение:**
- Дождаться срока из `retryAfter` (или заголовка `Retry-After`) и **не сокращать интервал повторов**: пока пауза действует, один вызов раз в 5 минут пропускается как проба восстановления, и агрессивный повтор занимает этот слот собой — метод остаётся закрытым для всего портала дольше, чем если бы вы просто подождали.
- Добавлять к паузе случайную величину, чтобы повторы разных клиентов не пришли одной волной.
- Облегчить сам вызов: меньше полей в `select`, меньше страница, более узкий фильтр или более узкий интервал дат. Пауза снимается первым успешным ответом, поэтому её снимает именно лёгкий вызов — тяжёлый снова упрётся в таймаут и продлит окно.
- Не искать эндпоинт для снятия паузы — его нет, и вмешательство не требуется.
- Сам конверт [`POST /v1/batch`](/docs/batch) под паузу не попадает: он объединяет разные методы, и его собственная задержка не говорит о том, какие из них перестали отвечать.

---

## `OPERATION_TIME_LIMIT` (429)

Битрикс24 приостановил ЭТОТ метод примерно на 5 минут, потому что метод исчерпал бюджет рабочего времени на портале. Отказ приходит и когда его прислал сам портал, и когда Вайбкод отбивает вызов на входе, зная, что пауза ещё действует.

```json
{
  "success": false,
  "error": {
    "code": "OPERATION_TIME_LIMIT",
    "message": "Bitrix24 operation-time limiter banned crm.item.list on this portal, retry in 245s",
    "userMessage": "Битрикс24 приостановил этот запрос на несколько минут: метод исчерпал лимит рабочего времени на портале. Дождитесь срока из Retry-After — остальные методы работают.",
    "hint": "Bitrix24 banned THIS method on this portal for ~5 minutes because it exhausted the portal's operating-time budget. Honor Retry-After — the same call cannot succeed sooner and retrying earlier only adds load. Other methods on the portal are unaffected; spread heavy reads over time or narrow them (fewer fields, smaller pages, POST /v1/batch).",
    "retryAfter": 245,
    "scope": "apiKey"
  }
}
```

**Заголовки ответа:**

```
Retry-After: 245
```

**Причины:**
- Бюджет рабочего времени Битрикс24 считает на скользящем окне.
- Пауза адресная: `scope: "apiKey"` означает, что Битрикс24 приостановил связку «ваш ключ + этот метод». Другие методы работают, и другие ключи портала тот же метод вызывать могут. Контраст — [`TIMEOUT_QUARANTINE`](#timeout_quarantine-429) со `scope: "portal"`: там пауза общая для всего портала.
- Запрос не был выполнен — повтор безопасен, в том числе для методов записи.
- Код приходит и внутри `200`-ответа — на подвызовах [`POST /v1/batch`](/docs/batch), которые Вайбкод исполняет отдельными запросами (`data.errors[<id>]`), и на элементах батча одной сущности (`data[i].error`). У `200`-конверта нет заголовка `Retry-After` для отдельного подвызова, поэтому срок приходит полем `retryAfter`, а `scope` и `hint` — те же, что в одиночном `429`. Поля `userMessage` в конверте нет.

**Решение:**
- Дождаться срока из `retryAfter` (или заголовка `Retry-After`): раньше этого срока тот же вызов не пройдёт, а повторы только добавляют нагрузку.
- Разнести тяжёлые чтения по времени, а не запускать их пачкой.
- Облегчить вызовы: меньше полей в `select`, меньше страница, объединение через [`POST /v1/batch`](/docs/batch).

## Смотрите также

- [Коды ошибок](/docs/errors)
- [Повторы и обработка ошибок в коде](/docs/errors/handling)
- [Лимиты и оптимизация](/docs/optimization)
- [Batch](/docs/batch)
