# Ошибки и лимиты

> CardSdkError и все коды ошибок — что вызывает каждую и что с ней делать, а также все лимиты протокола карточек в одной таблице.

Source: https://docs.neurosquad.ai/ru/card-sdk/api/errors

## `CardSdkError`

Любой отказ — от приложения или от собственных проверок SDK ещё до того, как запрос покинет
карточку, — это `CardSdkError`:

```ts
import { CardSdkError, isCardSdkError } from '@neurosquad/card-sdk'

async function saveReport(text: string): Promise<void> {
  try {
    await card.fs.writeText('reports/latest.md', text, { createDirs: true })
  } catch (error) {
    if (isCardSdkError(error, 'PERMISSION_DENIED')) {
      card.ui.toast(`This needs the ${error.permission} permission`)
    } else if (isCardSdkError(error, 'RATE_LIMITED')) {
      await new Promise((resolve) => setTimeout(resolve, error.retryAfterMs ?? 1000))
      return saveReport(text)
    } else if (error instanceof CardSdkError) {
      card.log.error(error.code, error.method, error.hostMessage, error.data)
    } else {
      throw error
    }
  }
}
```

| Свойство | Что это |
| --- | --- |
| `code` | Один из кодов ниже. |
| `message` | `method: host message [CODE] — hint`, готово для журнала. |
| `hostMessage` | Только сообщение приложения (по-английски, для разработчиков — пользователям показывайте свой текст). |
| `method` | Метод, который упал, если ошибка пришла из вызова. |
| `data` | Подробности: ошибки схемы, `{ permission }`, `{ retryAfterMs }`, `{ conflict }`… |
| `hint` | Подсказка в одну строку — для кодов, у которых она есть. |
| `permission` | Для `PERMISSION_DENIED`: недостающее разрешение. |
| `retryAfterMs` | Для `RATE_LIMITED`: сколько ждать. |
| `issues` | Для `INVALID_PARAMS` / `BAD_REQUEST`: `{ path, keyword, message }[]` — где параметры не совпали со схемой. |

`isCardSdkError(error, code?)` — защитник типа, при желании для одного кода.

## Коды ошибок

| Код | Значит | Обычно |
| --- | --- | --- |
| `BAD_REQUEST` | Сообщение повреждено или его параметры — не простой JSON. | В параметрах `Date`, `Map` или экземпляр класса — передавайте простые данные. |
| `INVALID_PARAMS` | Параметры не подходят под схему метода. | Точный путь — в `error.issues`. А также значение порта, не прошедшее схему, или незаданный `{{secret:…}}`. |
| `METHOD_NOT_FOUND` | Приложение не знает этот метод. | Старое приложение — проверяйте через `card.host.supports()`. |
| `PERMISSION_DENIED` | У пакета нет разрешения. | Объявите его в манифесте или, если оно необязательное, попросите через `card.permissions.request()`. |
| `NOT_CONNECTED` | Целевая карточка или агент не соединены с вашей стрелкой. | Попросите пользователя её провести. |
| `NOT_FOUND` | Нет такой карточки, агента, ключа, файла или порта. | |
| `QUOTA_EXCEEDED` | Квота исчерпана: байты или ключи хранилища, созданные карточки, наблюдатели за файлами, полная очередь промптов агента. | Удалите старые данные, остановите старых наблюдателей, подождите. |
| `RATE_LIMITED` | Слишком много вызовов. Сколько ждать — в `data.retryAfterMs`. | Объединяйте вызовы, откладывайте, отступайте. (Заголовок, статус, бейдж, обзор и внимание из-за этого никогда не отклоняются — SDK схлопывает и повторяет их.) |
| `TOO_LARGE` | Сообщение, значение или ответ больше лимита. | См. [Лимиты](#limits). |
| `TIMEOUT` | Нет ответа вовремя (запрос к порту, команда, сетевой запрос). | |
| `BUDGET_PAUSED` | Воркспейс вышел за бюджет; программные промпты отклоняются. | Пользователь поднимает лимит в карточке [Budget](https://docs.neurosquad.ai/ru/cards/budget). |
| `BUSY` | Агент посреди хода, а вы указали `whenBusy: 'fail'`. | |
| `HOST_NOT_ALLOWED` | `net.fetch` к хосту вне выданных или к хосту, который резолвится в заблокированный адрес. | Добавьте хост в разрешение `network`. |
| `NETWORK_ERROR` | Сбой DNS, соединения, TLS или потока. | |
| `FS_DENIED` | Путь вне папки воркспейса, внутри `.git/` или через ссылку, ведущую наружу. | Используйте относительный путь. |
| `FS_ERROR` | Любая другая проблема с файлом; `data.conflict`, если не совпал `ifMtimeMs`. | |
| `NOT_VISIBLE` | Нужно, чтобы карточка была на экране: диалоги, ссылки, полёт камеры, запросы разрешений, промпты агенту в опасном режиме. | Повторите, когда `card.visibility === 'visible'`. |
| `USER_CANCELLED` | Пользователь отказался (подтверждение, промпт агенту в опасном режиме) или вызов отменён. | |
| `UNAVAILABLE` | Цель не запущена, воркспейс не открыт, карточка усыплена или соединение закрыто. | |
| `PROTOCOL_MISMATCH` | Карточка сделана под более новый протокол, чем знает приложение. | Пользователь обновляет NeuroSquad. |
| `NOT_READY` | Вызов сделан до завершения рукопожатия. | Дождитесь `connect()`. |
| `INTERNAL` | Ошибка в приложении. | Сообщите о ней, приложив журнал карточки. |

## Лимиты

Все лимиты есть в `card.limits` (константа `LIMITS` из SDK). Дешёвые SDK проверяет до отправки;
приложение соблюдает все.

| Область | Лимит |
| --- | --- |
| **Сообщения** | до 1 МБ каждое (запросы `fs.write` и `net.fetch` и ответы `fs.read`, `fs.list`, `net.fetch` — до 12 МБ); до 64 вызовов одновременно (сверх этого SDK ставит их в очередь); 200 вызовов/с, всплески до 400; значения не глубже 64 уровней и не больше 200 000 узлов |
| **Пакет** | архив до 50 МБ; распакованный до 100 МБ; до 5 000 файлов; каждый до 20 МБ; пути до 240 символов и 20 уровней; манифест до 256 КБ; иконка до 128 КБ |
| **Манифест** | до 40 настроек; до 16 входов и 16 выходов; до 32 инструментов; до 32 сетевых хостов; схемы до 500 узлов и 16 уровней, `enum` до 256 вариантов и 16 КБ, `const` до 4 КБ |
| **Хранилище** | ключ до 256 символов; значение до 1 МБ; до 10 000 ключей; 5 МБ на карточку, 20 МБ на пакет |
| **Сеть** | тело до 5 МБ; ответ до 10 МБ; 6 одновременно; 120 в минуту; до 5 редиректов; тайм-аут 30 с (максимум 120 с), включая тело; до 4 потоков, каждый закрывается после 5 минут тишины или 256 МБ |
| **Файлы** | чтение и запись до 10 МБ; список до 5 000 записей; до 20 наблюдателей |
| **Агенты** | промпт до 20 000 символов, 6 в минуту на карточку (метод и порт вместе), до 10 в очереди на агента; команда до 20 000 символов; 30 команд в минуту на карточку (`run` и порт терминала вместе, тайм-аут до 120 с), `write` 60 в минуту; экран до 500 строк; вывод доставляется каждые 100 мс или 64 КБ |
| **Инструменты** | результат до 1 МБ; тайм-аут 30 с (максимум 120 с); прогресс 4 раза в секунду |
| **Порты** | 20 сообщений/с на выход; сохраняемое значение до 256 КБ; тайм-аут запроса 30 с (максимум 120 с) |
| **Интерфейс карточки** | заголовок до 120 (30 в минуту); статус до 80, статус/бейдж/обзор — по 120 в минуту; строки обзора до 160; тост до 280 (один в 2 с); текст подтверждения до 1 000 (10 в минуту); до 12 пунктов меню (30 изменений в минуту); `settings.set` 60 в минуту; `tools.setEnabled` 30 в минуту; `usage.summary` 6 в минуту; внимание раз в 10 с; полёт камеры раз в 5 с; изменение размера раз в 500 мс; до 4 созданных карточек; буфер обмена раз в секунду, до 1 МБ |
| **Журнал** | строка до 2 000 символов; 50 строк в секунду |
| **Страницы** | во всём приложении работает до 24 страниц карточек; из них в фоне — до 8; усыпление через 60 с скрытности, на сохранение — 1 с; пульс каждые 5 с, «не отвечает» через 15 с; готовность — в течение 10 с после запуска |
