Перейти к содержимому
OmniRoute source

Troubleshooting (Русский)

Впервые используете OmniRoute? Начните здесь — эти решения устраняют 90% проблем:

Что вы видите Что это означает Что делать
“Не удаётся подключиться” OmniRoute не запущен Выполните omniroute или docker restart omniroute
“Недействительный API-ключ” Ваш ключ неверен или истёк Скопируйте ключ заново с сайта провайдера
“Превышен лимит запросов” Вы отправляете слишком много запросов Подождите 1 минуту или используйте model: "auto" для автоматического переключения
“Квота исчерпана” Вы исчерпали бесплатную или оплаченную квоту Подключите больше провайдеров или используйте бесплатных провайдеров (Kiro, Pollinations)
“Медленные ответы” Провайдер перегружен или находится далеко Используйте model: "auto/fast" или подключите более быстрого провайдера (Groq, Cerebras)
“Используется не тот провайдер” auto выбрал другого провайдера Это нормально! auto выбирает лучший вариант. Укажите конкретного провайдера через model: "openai/gpt-4o"
“502 Bad Gateway” Провайдер недоступен Подождите и повторите попытку или используйте model: "auto" для переключения между провайдерами
“401 Unauthorized” Ваши учётные данные неверны Проверьте API-ключ или повторно выполните аутентификацию через OAuth
“omniroute is not recognized” В Windows PATH отсутствуют глобальные модули Node.js Добавьте глобальный префикс npm в Windows PATH. Найдите его с помощью npm config get prefix.
“429 Too Many Requests” Сработало ограничение частоты запросов Подождите 1 минуту или подключите больше провайдеров

Проблема не решена? См. подробное устранение неполадок ниже или задайте вопрос в Discord.



Ограничение частоты запросов у бесплатных провайдеров (429 / 400 / 401)

Заголовок раздела «Ограничение частоты запросов у бесплатных провайдеров (429 / 400 / 401)»

Симптом: при использовании model: "auto" с бесплатными провайдерами или провайдерами без аутентификации (opencode, auggie и т. д.) вместо ответов периодически возвращаются ошибки HTTP 429, 400 или 401. Если спустя несколько секунд повторить тот же запрос, он выполняется успешно, однако автоматизация (задания cron, агенты, скрипты) прерывается при первой же ошибке.

Основная причина: одновременно проявляются три независимых режима отказа:

  1. Ограничение частоты запросов провайдером (429): на бесплатных тарифах может действовать квота на определённый временной интервал. Всплеск параллельных вызовов исчерпывает её, поэтому следующий запрос отклоняется до сброса интервала.
  2. Неработающая модель в режиме сквозной передачи (400/401): пулы auto/* могут включать модели сквозной передачи от opencode, зарегистрированные в каталоге, но не имеющие действующих учётных данных (например, oc/north-mini-code-free → 401). Автоматический маршрутизатор пробует такую модель, получает ошибку, и она передаётся вызывающей стороне до того, как успевает сработать резервное переключение.
  3. Усиление из-за параллелизма (429 под нагрузкой): когда несколько сеансов агентов или cron одновременно обращаются к auto, совокупная частота запросов превышает допустимую для бесплатных провайдеров, поэтому легитимные вызовы помечаются как злоупотребление.

Проверенное решение (сообщено сообществом, 2026-08-10): настройте три переменные среды так, чтобы ротация, ограничение параллелизма и резервное переключение компенсировали нестабильность бесплатного тарифа, а не приводили к сбою:

Окно терминала
export OMNIROUTE_ROTATE_ON_400=true # перейти к другой модели или другому провайдеру при 400/401 (пропускает неработающие модели сквозной передачи)
export OMNIROUTE_CHAT_MAX_HEAVY_IN_FLIGHT=4 # явный верхний предел допуска ресурсоёмких запросов (по умолчанию не задан: количество запросов не ограничивается, см. примечание ниже)
export OMNIROUTE_CHAT_ADMISSION_QUEUE_MS=5000 # более длительное ограниченное ожидание доступности ресурсов для ресурсоёмких запросов вместо немедленной повторяемой ошибки 503

Задайте эти переменные в среде процесса OmniRoute (демона, например через plist-файл LaunchAgent или systemctl edit), затем перезапустите OmniRoute. Флаг ротации даёт наибольший эффект: он превращает критический сбой в незаметную повторную попытку через работоспособного провайдера из пула.

Примечание: OMNIROUTE_CHAT_MAX_HEAVY_IN_FLIGHT ограничивает количество одновременно выполняемых ресурсоёмких запросов с длинным контекстом; это ограничение допуска, а не ограничитель частоты запросов провайдера. Обновление #503-fanout: эта переменная больше не задаётся по умолчанию (теперь она применяется только при явной настройке, как показано выше) — вместо этого допуск ресурсоёмких запросов регулируется автоматически вычисляемым бюджетом байтов (OMNIROUTE_CHAT_MAX_INFLIGHT_BYTES), который масштабируется в соответствии с фактическим ограничением памяти хоста. Поэтому в новой установке должно возникать значительно меньше отказов 503 chat_admission_busy, даже если эта переменная вообще не задана; её явная настройка по-прежнему работает точно так, как описано в документации. Явно заданный бюджет байтов ограничивается диапазоном от 8 MiB до 2 GiB. Ошибка 413 body_exceeds_budget не является временной: увеличьте бюджет байтов, уменьшите OMNIROUTE_CHAT_HARD_MAX_BODY_BYTES или увеличьте лимит памяти процесса. Сброс нагрузки inflight_bytes_budget означает временную конкуренцию за ресурсы, поэтому запрос можно повторить. Ограничение частоты запросов для отдельных провайдеров (open-sse/services/rateLimitManager.ts) независимо регулируется переменными RATE_LIMIT_MAX_WAIT_MS, RATE_LIMIT_MAX_QUEUE_DEPTH и RATE_LIMIT_AUTO_ENABLE — см. .env.example.

Как проверить, что исправление сработало: запустите агент/cron два раза подряд с небольшим интервалом и убедитесь, что оба запуска завершились успешно. До исправления второй запуск обычно завершался ошибкой 429/401. После исправления ошибки (если они возникают) прозрачно обрабатываются повторными попытками, и вызов завершается успешно. Также можно выполнить curl /monitoring/health и отслеживать поле rateLimitedUntil в подключениях провайдеров, а также circuitBreakers.providerBreakers[].state для затронутых провайдеров — состояние может быть CLOSED, DEGRADED, OPEN или HALF_OPEN (см. src/shared/utils/circuitBreaker.ts), а провайдер, у которого продолжают возникать ошибки, будет переходить между состояниями CLOSED → DEGRADED → OPEN, пока по окончании интервала сброса не будет разрешён пробный запрос (HALF_OPEN).

Если ошибка 429 по-прежнему возникает: активная учётная запись этого провайдера действительно исчерпала свою квоту (а не просто достигла ограничения частоты запросов). Добавьте вторую учётную запись того же провайдера в панели OmniRoute → Providers → Accounts или подключите ещё одного бесплатного провайдера (например, routeway, auggie). Ротация помогает только при временных ошибках ограничения частоты запросов/400/401; при полном исчерпании квоты требуются вторые учётные данные или другой провайдер.

Если ошибка 403 возникает при использовании моделей компьютерного зрения (auto/vision, bazaarlink/*): в подключённой учётной записи отсутствует платный тариф, включающий компьютерное зрение, либо у ключа API недостаточно разрешений. Убедитесь в панели провайдера, что область действия ключа включает компьютерное зрение/мультимодальность, или подключите учётную запись с платным тарифом и оставьте её в качестве целевой для задач компьютерного зрения.


При выполнении npm install -g omniroute вы можете увидеть множество предупреждений, таких как npm warn ERESOLVE, уведомления о peer-зависимостях и сообщения deprecated. Это ожидаемо и не представляет опасности. Установка выполнена успешно, если в выводе присутствует строка added <N> packages.

Чтобы скрыть предупреждения о разрешении peer-зависимостей, используйте поддерживаемую OmniRoute форму команды установки:

Окно терминала
npm install -g omniroute --legacy-peer-deps

--legacy-peer-deps скрывает только уведомления ERESOLVE и предупреждения о peer-зависимостях. Уведомления об устаревших пакетах остаются видимыми, поскольку они поступают от транзитивных сторонних пакетов; они не означают, что установка завершилась неудачно.

Предупреждения возникают из-за устаревших диапазонов peer-зависимостей в сторонних пакетах, которые OmniRoute не контролирует:

  1. marked-terminal требует marked >=1 <16, но обнаружен marked@18 — на практике всё работает нормально; диапазон peer-зависимости в исходном пакете просто устарел.
  2. deprecated prebuild-install@7.1.3 — транзитивная вспомогательная утилита для загрузки нативных бинарных файлов. Она не используется для установки привязки транспорта wreq-js с зафиксированной версией и не означает, что настройка транспорта провайдера веб-cookie завершилась неудачно.

Никаких действий не требуется — полностью скрыть эти предупреждения без создания форков исходных пакетов невозможно.


Если запрос Gemini Web возвращает 503 с сообщением о том, что Playwright Chromium не установлен, это означает, что npm-пакет присутствует, но бинарный файл браузера отсутствует. Playwright намеренно отделяет загрузку браузеров от установки npm-пакета, поэтому такой ответ ожидаем до установки браузера.

При глобальной установке через npm установите Chromium из каталога пакета OmniRoute, чтобы кеш браузера относился к той же установке Playwright:

Окно терминала
cd "$(npm root -g)/omniroute"
npx playwright install chromium

После установки перезапустите OmniRoute, а затем повторите запрос Gemini Web. Если вы запускаете OmniRoute из образа Docker, используйте образ -web (или цель сборки runner-web), в который включены Chromium и его зависимости; базовый образ их не содержит.


Проблема Решение
Первый вход не работает Задайте INITIAL_PASSWORD в .env (жёстко заданного пароля по умолчанию нет)
Панель управления открывается на неверном порту Задайте PORT=20128 и NEXT_PUBLIC_BASE_URL=http://localhost:20128
Логи не записываются на диск Задайте APP_LOG_TO_FILE=true и убедитесь, что сбор логов вызовов включён
EACCES: доступ запрещён Задайте DATA_DIR=/path/to/writable/dir, чтобы переопределить ~/.omniroute
Стратегия маршрутизации не сохраняется Обновитесь до последнего выпуска v3.x (исправление схемы Zod для сохранения настроек было выпущено в более ранних версиях)
Сбой при входе / пустая страница Проверьте версию Node.js — см. раздел Совместимость с Node.js ниже
dlopen / slice is not valid mach-o file (macOS) Выполните cd $(npm root -g)/omniroute/app && npm rebuild better-sqlite3 && omniroute — см. раздел Пересборка нативного модуля в macOS ниже
Ошибка прокси «fetch failed» Убедитесь, что конфигурация прокси задана на правильном уровне — см. раздел Проблемы с прокси ниже
Docker curl: (56) Recv failure: Connection reset by peer Привязка порта Docker может выполняться к IPv6. Используйте -p 127.0.0.1:20128:20128, чтобы принудительно использовать IPv4, или проверьте с помощью curl -4. См. раздел IPv6 в Docker ниже
Антивирус помещает README.md в карантин Ложное срабатывание — см. раздел Ложные срабатывания антивируса ниже
Kaspersky определяет приложение Desktop как троян Поведенческое ложное срабатывание на неподписанный установщик — см. раздел Ложные срабатывания антивируса ниже

Avast/AVG помещает README.md в карантин с вердиктом MD:HttpRequest-inf[Susp]

Заголовок раздела «Avast/AVG помещает README.md в карантин с вердиктом MD:HttpRequest-inf[Susp]»

Это ложное срабатывание. Ничего не заражено, и никаких действий не требуется.

Avast и AVG используют эвристический алгоритм, который помечает обычные текстовые файлы и файлы Markdown, содержащие большое количество ссылок, похожих на HTTP-запросы. README.md OmniRoute входит в состав npm-пакета (он указан в package.json → files), поэтому при глобальной установке он оказывается по адресу node_modules/omniroute/README.md — и содержит около 15 примеров вида http://localhost:20128/... (конечные точки MCP HTTP/SSE, URL A2A .well-known и фрагменты с curl). Такой плотности ссылок достаточно, чтобы сработал эвристический алгоритм.

Если проблема появилась лишь недавно: тип содержимого файла не изменился. В README была расширена таблица конечных точек (добавлены MCP HTTP + SSE + A2A), а также появилось больше примеров с curl, из-за чего был превышен порог срабатывания.

Этот файл представляет собой неактивную документацию и не содержит исполняемого содержимого. Его можно безопасно восстановить из карантина.

Что делать:

  1. Остановите уведомления — добавьте каталог установки в исключения антивируса (Avast: Настройки → Исключения), указав путь к глобальному каталогу node_modules и/или каталогу данных OmniRoute (~/.omniroute/).
  2. Сообщите о ложном срабатывании — https://www.avast.com/false-positive-file-form.php, приложив помещённый в карантин файл README.md. Это решение поможет всем, поскольку причина заключается в чрезмерной реакции эвристического алгоритма производителя на текстовый файл.

Почему мы не «исправляем» это со своей стороны: во всех примерах используется http://localhost, а для localhost нельзя использовать https без сложностей с самоподписанными сертификатами. Искажать документацию ради обхода эвристического алгоритма одного производителя означало бы ухудшить её для всех читателей из-за ошибки сканера.

Kaspersky помечает настольное приложение как PDM:Trojan.Win32.Generic

Заголовок раздела «Kaspersky помечает настольное приложение как PDM:Trojan.Win32.Generic»

Это ложное срабатывание поведенческого эвристического алгоритма. Ничего не заражено. Префикс PDM: у Kaspersky означает, что вердикт вынесен модулем проактивной защиты (System Watcher), который оценивает действия установщика, а не сопоставляет его с известным вредоносным ПО. При срабатывании Kaspersky «откатывает» всю установку — удаляя уже записанные файлы, — поэтому приложение оказывается повреждено или отсутствует.

Помечаемые файлы являются стандартными компонентами заявленных зависимостей с открытым исходным кодом, включённых в настольное приложение, например:

  • resources/app/.build/next/node_modules/playwright-&lt;hash&gt;/lib/…/agentParser.js и workerProcessEntry.js — Playwright, библиотека автоматизации браузера, используемая для входа в сервисы поставщиков из приложения и чата на основе браузера.
  • resources/app/.build/next/node_modules/@wreq-js/binding-win32-&lt;arch&gt;-msvc-&lt;hash&gt;/wreq-js.win32-&lt;arch&gt;-msvc.node — закреплённая версия нативной привязки wreq-js, используемой для HTTP-запросов с цифровым отпечатком браузера к поставщикам, использующим веб-файлы cookie (&lt;arch&gt; — x64 или arm64).

Почему происходит срабатывание: установщик Windows пока не имеет цифровой подписи, поэтому неподписанный установщик NSIS обладает нулевой репутацией, а поведенческие эвристические алгоритмы работают с максимальной агрессивностью. В сочетании со встроенной нативной DLL и сотнями файлов .js, записываемых в %LOCALAPPDATA%\Programs\OmniRoute (включая каталоги пакетов с суффиксами-хешами из автономной сборки Next.js), этого достаточно для срабатывания эвристического алгоритма. Подписание кода запланировано; до его внедрения проблема может повторяться в новых выпусках.

Что делать:

  1. Сначала проверьте загруженный файл (это исключит возможность его подмены). В каждом выпуске публикуется файл latest.yml, поле sha512 которого (в формате base64) соответствует установщику OmniRoute.Setup.&lt;version&gt;.exe. В PowerShell, находясь в папке с установщиком, выполните:
    Окно терминала
    $b = [System.Security.Cryptography.SHA512]::Create().ComputeHash(
    [System.IO.File]::ReadAllBytes("$PWD\OmniRoute.Setup.&lt;version&gt;.exe"))
    [Convert]::ToBase64String($b)
    Результат должен совпадать со значением latest.yml → sha512. Если значения не совпадают, удалите файл и повторно загрузите его только со страницы выпусков GitHub.
  2. Восстановите и добавьте в исключения — восстановите удалённые при откате элементы из карантина и добавьте исключение для %LOCALAPPDATA%\Programs\OmniRoute (Kaspersky → Настройки → Угрозы и исключения), затем выполните повторную установку.
  3. Сообщите о ложном срабатывании — https://opentip.kaspersky.com/. Отправленные пользователями сообщения о ложных срабатываниях действительно ускоряют добавление файлов в список разрешённых.

Страница входа аварийно завершается или показывает ошибку «Module self-registration»

Заголовок раздела «Страница входа аварийно завершается или показывает ошибку «Module self-registration»»

Причина: Вы используете версию Node.js, которая не соответствует утверждённому OmniRoute минимальному уровню безопасной среды выполнения. Чаще всего это происходит при использовании более старой патч-версии Node 22 или 24, которая ниже минимальной версии с исправлениями безопасности, требуемой OmniRoute.

Симптомы:

  • На странице входа отображается пустой экран или ошибка сервера
  • В консоли отображается Error: Module did not self-register или похожие ошибки нативных привязок
  • На странице входа отображается оранжевый предупреждающий баннер с вашей версией Node, если среда выполнения не соответствует поддерживаемой политике безопасности

Решение:

  1. Установите поддерживаемую LTS-версию Node.js (рекомендуется Node.js 24.x):
    Окно терминала
    nvm install 24
    nvm use 24
  2. Проверьте версию: node --version должна выводить v24.0.0 или более новую версию в ветке 24.x LTS
  3. Переустановите OmniRoute: npm install -g omniroute
  4. Перезапустите: omniroute

Поддерживаемые безопасные версии: >=22.22.2 <23 или >=24.0.0 <27. Node.js 24.x LTS (Krypton) и Node.js 26 полностью поддерживаются.

Причина: npm v11 (поставляемый с Node.js 24+) по умолчанию блокирует сценарии установки для необязательных зависимостей. Поскольку better-sqlite3 указан в optionalDependencies и требует нативной компиляции (node-gyp rebuild), npm без уведомления пропускает его.

Симптомы:

  • Сервер аварийно завершается при запуске с ошибкой Cannot find module 'better-sqlite3'
  • ls node_modules/better-sqlite3 выводит «No such file or directory»
  • npm ls better-sqlite3 выводит (empty)

Решение:

  1. Разрешите сценарии установки и выполните повторную установку:
    Окно терминала
    npm approve-scripts better-sqlite3
    npm install
  2. Либо установите предварительно собранный пакет вручную:
    Окно терминала
    npm pack better-sqlite3@13.0.1
    tar -xzf better-sqlite3-*.tgz -C node_modules
    mv node_modules/package node_modules/better-sqlite3
    rm better-sqlite3-*.tgz
  3. Проверьте работоспособность: node -e "require('better-sqlite3')(':memory:').close(); console.log('OK')"

Причина: После глобальной установки npm install -g omniroute нативный бинарный файл better-sqlite3 внутри пакета может быть скомпилирован для другой архитектуры или ABI Node.js, отличающихся от используемых локально. Это часто встречается в macOS (как на Apple Silicon, так и на Intel), когда предварительно собранный бинарный файл не соответствует вашей среде.

Симптомы:

  • Сервер немедленно завершает работу при запуске с ошибкой dlopen
  • Ошибка содержит slice is not valid mach-o file
  • Полный пример:
dlopen(/Users/&lt;user&gt;/.nvm/versions/node/v24.14.1/lib/node_modules/omniroute/app/node_modules/better-sqlite3/build/Release/better_sqlite3.node, 0x0001): tried: '...' (slice is not valid mach-o file)

Решение — пересоберите пакет для локальной среды (переход на более старую версию Node.js не требуется):

Окно терминала
cd $(npm root -g)/omniroute/app
npm rebuild better-sqlite3
omniroute

Примечание: Эта команда повторно компилирует нативную привязку для вашей локальной версии Node.js и архитектуры процессора, устраняя несовместимость бинарных файлов. Официально поддерживаемый диапазон сред выполнения — >=22.22.2 <23 или >=24.0.0 <27 (SUPPORTED_NODE_RANGE в src/shared/utils/nodeRuntimeSupport.ts, согласованный с полем engines в package.json). Node.js 24.x LTS (Krypton) и Node.js 26 полностью поддерживаются с better-sqlite3 v12.x.


При проверке провайдера отображается ошибка “fetch failed”

Заголовок раздела «При проверке провайдера отображается ошибка “fetch failed”»

Причина: Ранее конечная точка проверки API-ключа (POST /api/providers/validate) обходила конфигурацию прокси, что приводило к сбоям в средах, где требуется маршрутизация через прокси.

Исправление (v3.5.5+): Проблема устранена. Теперь проверка провайдера выполняется через runWithProxyContext с автоматическим учетом настроек прокси на уровне провайдера и глобальных настроек прокси.

Проверка состояния токена завершается ошибкой “fetch failed”

Заголовок раздела «Проверка состояния токена завершается ошибкой “fetch failed”»

Причина: При фоновом обновлении токена OAuth конфигурация прокси не определялась отдельно для каждого подключения.

Исправление (v3.5.5+): Теперь планировщик проверки состояния токенов определяет конфигурацию прокси для каждого подключения перед попыткой обновления. Обновитесь до v3.5.5+.

Прокси SOCKS5 возвращает ошибку “invalid onRequestStart method”

Заголовок раздела «Прокси SOCKS5 возвращает ошибку “invalid onRequestStart method”»

Причина: В Node.js 22 диспетчер undici@8 несовместим со встроенной реализацией fetch() в Node.

Исправление (v3.5.5+): Теперь OmniRoute использует собственную функцию fetch() из undici, когда активен диспетчер прокси, что обеспечивает согласованное поведение. Обновитесь до v3.5.5+.

MITM-прокси в WSL: приложения на рабочем столе хоста Windows не перехватываются

Заголовок раздела «MITM-прокси в WSL: приложения на рабочем столе хоста Windows не перехватываются»

Причина: MITM-прокси и его сертификат центра сертификации устанавливаются в среде, в которой работает OmniRoute. В WSL такой средой является гостевая система Linux, тогда как настольные ИИ-приложения (Kiro, Trae, Copilot, Zed, …) работают на хосте Windows. Приложения на хосте не доверяют хранилищу сертификатов гостевой системы и не используют ее системный прокси, поэтому перехват настольных приложений не выполняется.

Рекомендация: Запускайте OmniRoute непосредственно в той же ОС, что и настольные приложения, трафик которых вы хотите перехватывать (Windows для приложений Windows; аналогично для macOS/Linux). Если OmniRoute работает в WSL, а целевые приложения — на хосте, необходимо вручную добавить созданный сертификат центра сертификации в доверенные на хосте Windows и настроить параметры сети/прокси каждого приложения на использование конечной точки прокси WSL. Такая конфигурация не поддерживается и ненадежна.


Причина: Квота провайдера исчерпана.

Исправление:

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

Причина: Квота подписки исчерпана.

Исправление:

  • Добавьте резервную цепочку: cc/claude-opus-4-6 → glm/glm-4.7 → if/qwen3.8-max-preview
  • Используйте GLM/MiniMax как дешевый резервный вариант

OmniRoute автоматически обновляет токены. Если проблемы сохраняются:

  1. Панель управления → Провайдер → Переподключить
  2. Удалите подключение к провайдеру и добавьте его заново

Несколько учетных записей Kiro: вторая учетная запись делает первую недействительной

Заголовок раздела «Несколько учетных записей Kiro: вторая учетная запись делает первую недействительной»

Причина: Серверная часть Kiro допускает только один активный сеанс для каждой регистрации клиента OIDC. Если две учетные записи используют один и тот же зарегистрированный клиент (подключения, импортированные до v3.8.0), обновление токена одной учетной записи делает недействительным токен обновления другой.

Исправление (v3.8.0+): Повторно импортируйте затронутые подключения. Начиная с v3.8.0, для каждого нового подключения Kiro, созданного через Импорт токена, Вход через Google/GitHub или Автоимпорт, автоматически регистрируется собственный выделенный клиент OIDC. Таким образом, подключение полностью изолировано, и обновление одной учетной записи не влияет ни на какие другие учетные записи.

Подключения, импортированные до v3.8.0, не имеют отдельной регистрации клиента для каждого подключения. Эти подключения продолжают использовать общую конечную точку обновления социальной аутентификации. Чтобы обеспечить изоляцию, удалите старое подключение через Панель управления → Провайдеры и добавьте его заново, используя любой из трех способов импорта.

Подробное описание и пошаговые инструкции по одновременному добавлению двух учетных записей Kiro см. в файле docs/guides/KIRO_SETUP.md.


  1. Убедитесь, что BASE_URL указывает на запущенный экземпляр (например, http://localhost:20128)
  2. Убедитесь, что CLOUD_URL указывает на вашу облачную конечную точку (например, https://omniroute.dev)
  3. Значения NEXT_PUBLIC_* должны соответствовать значениям на стороне сервера

Симптом: Unexpected token 'd'... на облачной конечной точке при запросах без потоковой передачи.

Причина: Вышестоящий сервер возвращает данные SSE, тогда как клиент ожидает JSON.

Временное решение: Используйте stream=true для прямых облачных запросов. Локальная среда выполнения включает механизм резервного преобразования SSE→JSON.

Облако сообщает о подключении, но возвращает «Invalid API key»

Заголовок раздела «Облако сообщает о подключении, но возвращает «Invalid API key»»
  1. Создайте новый ключ на локальной панели управления (/api/keys)
  2. Запустите облачную синхронизацию: включите облако → выполните синхронизацию
  3. Старые или несинхронизированные ключи по-прежнему могут возвращать 401 в облаке

Симптомы: curl http://localhost:20128/v1/models возвращает curl: (56) Recv failure: Connection reset by peer. Панель управления и конечные точки без аутентификации работают, однако конечные точки с аутентификацией завершаются ошибкой — это выглядит как проблема с аутентификацией, но на самом деле ею не является.

Причина: Команда docker run -p 20128:20128 открывает порт как на 0.0.0.0 (IPv4), так и на :: (IPv6), однако процесс внутри контейнера прослушивает только IPv4. На хостах, где localhost сначала разрешается в ::1, соединение поступает на опубликованный порт IPv6, за которым нет слушателя → соединение сбрасывается.

Исправление:

  1. Быстрая диагностика: Выполните curl -4 http://localhost:20128/v1/models. Если команда работает с -4, но не работает без него, у вас несоответствие привязки IPv6.
  2. Постоянное исправление: Явно привяжитесь к IPv4, используя -p 127.0.0.1:20128:20128 в команде docker run:
    Окно терминала
    docker run -d --name omniroute --restart unless-stopped --stop-timeout 40 \
    -p 127.0.0.1:20128:20128 -v omniroute-data:/app/data diegosouzapw/omniroute:latest
    Это принудительно включает привязку к IPv4, а также предотвращает доступ к прокси через все интерфейсы хоста.

Инструмент CLI отображается как неустановленный

Заголовок раздела «Инструмент CLI отображается как неустановленный»
  1. Проверьте поля среды выполнения: curl http://localhost:20128/api/cli-tools/runtime/codex | jq
  2. Для переносимого режима используйте целевой образ runner-cli (CLI входят в комплект)
  3. Для режима монтирования с хоста задайте CLI_EXTRA_PATHS и смонтируйте каталог исполняемых файлов хоста только для чтения
  4. Если installed=true и runnable=false: исполняемый файл найден, но не прошёл проверку работоспособности
Окно терминала
curl -s http://localhost:20128/api/cli-tools/codex-settings | jq '{installed,runnable,commandPath,runtimeMode,reason}'
curl -s http://localhost:20128/api/cli-tools/claude-settings | jq '{installed,runnable,commandPath,runtimeMode,reason}'
curl -s http://localhost:20128/api/cli-tools/openclaw-settings | jq '{installed,runnable,commandPath,runtimeMode,reason}'

  1. Проверьте статистику использования в разделе «Панель управления → Использование»
  2. Смените основную модель на GLM/MiniMax
  3. Используйте бесплатный уровень (Qoder, Kiro) для некритичных задач
  4. Установите бюджеты расходов для каждого ключа API: «Панель управления → Ключи API → Бюджет»

Задайте APP_LOG_TO_FILE=true в файле .env. Журналы приложения записываются в каталог logs/. Артефакты запросов сохраняются в ${DATA_DIR}/call_logs/, когда конвейер журналирования вызовов включён в настройках. Если захват данных конвейером включён, задайте CALL_LOG_PIPELINE_CAPTURE_STREAM_CHUNKS=false, чтобы исключить данные потоковых фрагментов, или измените CALL_LOG_PIPELINE_MAX_SIZE_KB, чтобы настроить ограничение размера артефактов в КБ.

Окно терминала
# Панель мониторинга состояния
http://localhost:20128/dashboard/health
# Проверка состояния API
curl http://localhost:20128/api/monitoring/health
  • Основное состояние: ${DATA_DIR}/storage.sqlite (поставщики, комбинации, псевдонимы, ключи, настройки)
  • Использование: таблицы SQLite в storage.sqlite (usage_history, call_logs, proxy_logs) + необязательный каталог ${DATA_DIR}/call_logs/
  • Журналы приложения: &lt;repo&gt;/logs/... (когда задано APP_LOG_TO_FILE=true)
  • Артефакты журналов вызовов: ${DATA_DIR}/call_logs/YYYY-MM-DD/..., когда включён конвейер журналирования вызовов

Действие Очистить историю на странице журналов запросов очищает call_logs, устаревшие request_detail_logs и локальный каталог артефактов ${DATA_DIR}/call_logs/.


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

Решение:

  1. Перейдите в раздел Панель управления → Настройки → Отказоустойчивость
  2. Проверьте карточку автоматического выключателя соответствующего провайдера
  3. Нажмите Сбросить все, чтобы сбросить все автоматические выключатели, или дождитесь истечения периода ожидания
  4. Перед сбросом убедитесь, что провайдер действительно доступен

Провайдер постоянно активирует автоматический выключатель

Заголовок раздела «Провайдер постоянно активирует автоматический выключатель»

Если провайдер постоянно переходит в состояние OPEN:

  1. Проверьте характер сбоев в разделе Панель управления → Состояние → Состояние провайдеров
  2. Перейдите в раздел Настройки → Отказоустойчивость → Профили провайдеров и увеличьте порог сбоев
  3. Проверьте, не изменил ли провайдер ограничения API и не требуется ли повторная аутентификация
  4. Проверьте телеметрию задержек — высокая задержка может приводить к сбоям из-за превышения времени ожидания

  • Используйте идентификатор модели, первый сегмент которого соответствует провайдеру, для которого у вас есть учётные данные (openai/whisper-1, openrouter/deepgram/nova-3). Для простого идентификатора deepgram/nova-3 требуется собственный ключ Deepgram.
  • Убедитесь, что провайдер подключён в разделе Панель управления → Провайдеры

Результат транскрибации пуст или возникает ошибка

Заголовок раздела «Результат транскрибации пуст или возникает ошибка»
  • Проверьте поддерживаемые форматы аудио: mp3, wav, m4a, flac, ogg, webm
  • Убедитесь, что размер файла не превышает ограничения провайдера (обычно < 25 МБ)
  • Проверьте действительность ключа API провайдера в его карточке

Используйте раздел Панель управления → Транслятор для отладки проблем с преобразованием форматов:

Режим Когда использовать
Песочница Сравнивайте входной и выходной форматы рядом — вставьте запрос, вызывающий ошибку, чтобы увидеть результат преобразования
Тестер чата Отправляйте сообщения в реальном времени и изучайте полную полезную нагрузку запроса и ответа, включая заголовки
Тестовый стенд Запускайте пакетные тесты для разных комбинаций форматов, чтобы определить, какие преобразования не работают
Мониторинг в реальном времени Наблюдайте за потоком запросов в реальном времени, чтобы выявлять периодически возникающие проблемы с преобразованием
  • Теги рассуждений не отображаются — проверьте, поддерживает ли целевой провайдер рассуждения, а также настройку бюджета рассуждений
  • Вызовы инструментов пропадают — при некоторых преобразованиях форматов неподдерживаемые поля могут удаляться; проверьте это в режиме «Песочница»
  • Системный промпт отсутствует — Claude и Gemini обрабатывают системные промпты по-разному; проверьте результат преобразования
  • SDK возвращает необработанную строку вместо объекта — исправлено в v1.x; средство очистки ответов удаляет нестандартные поля (x_groq, usage_breakdown и т. д.), вызывающие ошибки валидации Pydantic в OpenAI SDK. Если проблема по-прежнему возникает в v3.x+, сообщите о ней.
  • GLM/ERNIE отклоняет роль system — исправлено в v1.x; нормализатор ролей автоматически объединяет системные сообщения с пользовательскими для несовместимых моделей. Если проблема по-прежнему возникает в v3.x+, сообщите о ней.
  • Роль developer не распознаётся — исправлено в v1.x; для провайдеров, отличных от OpenAI, она автоматически преобразуется в system. Если проблема по-прежнему возникает в v3.x+, сообщите о ней.
  • json_schema не работает с Gemini — исправлено в v1.x; теперь response_format преобразуется в responseMimeType + responseSchema Gemini. Если проблема по-прежнему возникает в v3.x+, сообщите о ней.

Автоматическое ограничение частоты запросов не срабатывает

Заголовок раздела «Автоматическое ограничение частоты запросов не срабатывает»
  • Автоматическое ограничение частоты запросов применяется только к провайдерам с API-ключами (не к OAuth/подписке)
  • Убедитесь, что в разделе Настройки → Отказоустойчивость → Профили провайдеров включено автоматическое ограничение частоты запросов
  • Проверьте, возвращает ли провайдер коды состояния 429 или заголовки Retry-After

Профили провайдеров поддерживают следующие настройки:

  • Базовая задержка — начальное время ожидания после первого сбоя (по умолчанию: 1 с)
  • Максимальная задержка — верхний предел времени ожидания (по умолчанию: 30 с)
  • Множитель — степень увеличения задержки при каждом последовательном сбое (по умолчанию: 2x)

Предотвращение «лавинообразного наплыва»

Заголовок раздела «Предотвращение «лавинообразного наплыва»»

Когда множество одновременных запросов поступает к провайдеру с ограниченной частотой запросов, OmniRoute использует мьютекс и автоматическое ограничение частоты, чтобы выполнять запросы последовательно и предотвращать каскадные сбои. Для провайдеров с API-ключами это происходит автоматически.

Запросы чата завершаются ошибкой 503 / chat_admission_busy

Заголовок раздела «Запросы чата завершаются ошибкой 503 / chat_admission_busy»

Симптомы:

  • Конечная точка дополнений чата возвращает допускающий повторную попытку ответ 503 с кодом ошибки chat_admission_busy.
  • Ответ содержит Retry-After. Начиная с #12135 значение определяется на основе наблюдаемой занятости — выбирается большее из времени, которое запрос уже ожидал в пределах окна OMNIROUTE_CHAT_ADMISSION_QUEUE_MS, и времени удержания текущих тяжеловесных разрешений; результат округляется вверх до целого количества секунд и ограничивается 60 секундами. При незанятом шлюзе сохраняются прежние минимальные значения: 2 секунды для пути на основе байтов и 1 секунда для пути на основе структуры (который также включает reason: "structure_limit").
  • Это может происходить, пока другой тяжеловесный запрос чата или длительный потоковый ответ всё ещё находится в процессе выполнения.

Тело ответа для пути на основе байтов:

{
"error": {
"message": "Chat admission capacity is temporarily unavailable. Retry shortly.",
"type": "server_error",
"code": "chat_admission_busy"
}
}

Ответ для пути на основе структуры использует тот же тип и код, но с сообщением Local chat admission capacity is busy for this structurally heavy request; upstream provider routing was not attempted. Retry shortly. и reason: "structure_limit". При пороговых значениях по умолчанию запрос считается структурно тяжеловесным, если он содержит не менее 200 сообщений, не менее 64 инструментов или не менее 32,000 предполагаемых токенов либо если ограниченная оценка структуры исчерпывает лимиты в 10,000 посещённых узлов или глубину 12.

Причина: Это намеренный сброс нагрузки внутри OmniRoute, а не сбой вышестоящего провайдера. Каждый процесс использует локальный для процесса предохранитель, чтобы зарезервировать ограниченную ёмкость для тяжеловесных запросов до сохранения и разбора большого тела запроса. Тяжеловесное разрешение удерживается в течение всего времени существования SSE-ответа.

#503-fanout: до этого исправления предохранитель ограничивал параллелизм фиксированным ЧИСЛОМ запросов (OMNIROUTE_CHAT_MAX_HEAVY_IN_FLIGHT, по умолчанию 1) независимо от объёма памяти хоста, поэтому веерное выполнение запросов агентами программирования (несколько субагентов/CLI, тела запросов обычно > 256 КБ) снижало эффективный параллелизм примерно до 1 и приводило к ошибкам 503 при совершенно нормальной нагрузке. Теперь предохранитель настраивается автоматически: он управляется автоматически вычисляемым БАЙТОВЫМ бюджетом приёма (OMNIROUTE_CHAT_MAX_INFLIGHT_BYTES), размер которого определяется по фактическому лимиту памяти процесса, а также учитывает оперативный сигнал нагрузки на ресурсы — поэтому запросы сбрасываются только тогда, когда хост действительно испытывает нехватку памяти, а не просто потому, что одновременно поступило более одного тяжеловесного запроса. Прежнее ограничение по количеству (OMNIROUTE_CHAT_MAX_HEAVY_IN_FLIGHT) по-прежнему соблюдается, но только если вы зададите его явно.

Когда ёмкость занята, тяжеловесный запрос сначала ожидает освобождения слота в течение не более OMNIROUTE_CHAT_ADMISSION_QUEUE_MS (по умолчанию 2000, значение 0 отключает ожидание), прежде чем вернуть допускающий повторную попытку ответ 503. Ограниченное ожидание предусмотрено для того, чтобы клиенты агентного типа (OpenCode, Claude Code, Cursor), которые параллельно запускают множество тяжеловесных подзапросов, последовательно обрабатывали всплеск, а не исчерпывали весь бюджет повторных попыток из-за немедленных отказов и не завершались в середине задачи. Текущая занятость тяжеловесными разрешениями, рассчитанный байтовый бюджет и фактическая степень нагрузки доступны по адресу GET /api/monitoring/health → chatAdmission (inflightBytes, maxInflightBytes, budgetSource, pressureSeverity, countCapEnabled) — проверьте их, прежде чем изменять какую-либо переменную окружения. Настройки → Отказоустойчивость → Очередь запросов → Параллельные запросы не управляет этим механизмом; эта настройка управляет отдельным механизмом очереди запросов к провайдеру.

Исправление:

  1. Сначала повторите запрос. Клиенты должны учитывать Retry-After и использовать задержку, а не немедленно повторять запрос.
  2. Перед настройкой чего-либо проверьте /api/monitoring/health → chatAdmission. Значение countCapEnabled: false и достаточно большое maxInflightBytes означают, что автоматически рассчитанный бюджет уже работает должным образом; значение pressureSeverity, равное high/critical, означает, что хост действительно испытывает нехватку памяти — это нельзя исправить переменной окружения для управления допуском, требуется больше оперативной памяти или меньшая рабочая нагрузка.
  3. Только если /api/monitoring/health показывает, что автоматически рассчитанный бюджет действительно слишком мал для вашего хоста (что бывает редко — он уже масштабируется от контейнера до физического сервера), переопределите его напрямую с помощью OMNIROUTE_CHAT_MAX_INFLIGHT_BYTES, а не возвращайтесь к устаревшему ограничению по количеству запросов.

Актуальные настройки допуска см. в справочнике по переменным окружения.


Необязательная таксономия сбоев RAG / LLM (16 проблем)

Заголовок раздела «Необязательная таксономия сбоев RAG / LLM (16 проблем)»

Некоторые пользователи OmniRoute размещают шлюз перед стеками RAG или агентными системами. В таких конфигурациях часто наблюдается странная картина: OmniRoute выглядит исправным (провайдеры доступны, профили маршрутизации настроены правильно, предупреждений об ограничении частоты запросов нет), но итоговый ответ всё равно оказывается неверным.

На практике такие инциденты обычно возникают в нижестоящем конвейере RAG, а не в самом шлюзе.

Если вам нужен общий словарь для описания таких сбоев, можно использовать WFGY ProblemMap — внешний текстовый ресурс с лицензией MIT, в котором определены шестнадцать повторяющихся шаблонов сбоев RAG / LLM. На высоком уровне он охватывает:

  • отклонение поиска от цели и нарушение границ контекста
  • пустые или устаревшие индексы и векторные хранилища
  • несоответствие эмбеддингов и семантики
  • проблемы со сборкой промптов и контекстным окном
  • логические сбои и чрезмерно уверенные ответы
  • сбои длинных цепочек и координации агентов
  • отклонение памяти и ролей в мультиагентных системах
  • проблемы с порядком развёртывания и начальной загрузки

Идея проста:

  1. При расследовании некорректного ответа зафиксируйте:
    • задачу и запрос пользователя
    • маршрут или комбинацию провайдеров в OmniRoute
    • весь контекст RAG, использованный нижестоящими компонентами (полученные документы, вызовы инструментов и т. д.)
  2. Сопоставьте инцидент с одним или двумя номерами WFGY ProblemMap (No.1 … No.16).
  3. Сохраните номер в собственной панели мониторинга, рабочей инструкции или системе отслеживания инцидентов рядом с журналами OmniRoute.
  4. Используйте соответствующую страницу WFGY, чтобы определить, нужно ли изменить стек RAG, компонент поиска или стратегию маршрутизации.

Полный текст и конкретные инструкции доступны здесь (лицензия MIT, только текст):

README WFGY ProblemMap

Этот раздел можно пропустить, если за OmniRoute не используются конвейеры RAG или агентов.


Проблемы, характерные для выпуска v3.8.0, и доступные на данный момент способы их обхода. Если исправление появится в более позднем патч-выпуске, соответствующая запись будет обновлена или удалена.

Симптомы:

  • «Devin CLI не найден» или «сбой аутентификации» при вызове инструментов на базе Devin
  • Проверка среды выполнения CLI сообщает installed=false

Причины:

  • CLI_DEVIN_BIN указывает на несуществующий путь
  • Devin CLI не установлен на хосте

Исправление:

  1. Установите Devin CLI для своей платформы
  2. Задайте CLI_DEVIN_BIN=/usr/local/bin/devin (или фактический путь) в .env
  3. Перезапустите OmniRoute и повторите проверку через Панель управления → Инструменты CLI

Модель зависла в режиме ожидания (ручной сброс)

Заголовок раздела «Модель зависла в режиме ожидания (ручной сброс)»

Симптомы:

  • Модель продолжает отображаться в режиме ожидания даже после истечения срока его действия
  • При комбинированной маршрутизации запросы по-прежнему пропускают модель, хотя указанное время уже прошло

Ручной сброс:

  • Панель управления: Настройки → Периоды ожидания моделей → нажмите Повторно включить на карточке затронутой модели
  • API: DELETE /api/resilience/model-cooldowns с заголовками аутентификации для управления

Подключение к провайдеру Command Code завершается ошибкой 403

Заголовок раздела «Подключение к провайдеру Command Code завершается ошибкой 403»

Симптомы:

  • Ошибка 403 при проверке подключения к провайдеру Command Code
  • После нового добавления на карточке провайдера отображается статус «не авторизован»

Причина: Процесс OAuth не завершился (обратный вызов не был получен или токен не был сохранён).

Исправление:

  • Выполните omniroute providers в CLI, чтобы повторно запустить процесс OAuth, или
  • Повторно выполните OAuth через Панель управления → Провайдеры → Command Code → Переподключить

ModelScope возвращает чрезмерно длительные периоды ожидания при ошибках 429

Заголовок раздела «ModelScope возвращает чрезмерно длительные периоды ожидания при ошибках 429»

Симптомы:

  • После небольшой серии запросов ModelScope переходит в режим ожидания очень быстро или немедленно
  • При комбинированной маршрутизации ModelScope пропускается раньше ожидаемого

Причина: ModelScope отправляет специфичные для провайдера заголовки Retry-After. В v3.8.0 реализована отдельная обработка этих заголовков, поэтому более старые версии ошибочно интерпретируют их как общие указания по ограничению частоты запросов.

Исправление:

  • Убедитесь, что используете v3.8.0 или более позднюю версию
  • Убедитесь, что переключатель useUpstream429BreakerHints включён в разделе Настройки → Отказоустойчивость

OMNIROUTE_WS_BRIDGE_SECRET отсутствует в рабочей среде

Заголовок раздела «OMNIROUTE_WS_BRIDGE_SECRET отсутствует в рабочей среде»

Симптомы:

  • Ошибка 401 при каждом запросе к мосту WebSocket Codex/Responses во время работы на удалённом рабочем хосте
  • Сеанс установления соединения с мостом WebSocket закрывается сразу после подключения

Причина: Переменная среды OMNIROUTE_WS_BRIDGE_SECRET отсутствует в рабочей среде.

Исправление:

  1. Создайте случайный секрет: openssl rand -hex 32
  2. Задайте OMNIROUTE_WS_BRIDGE_SECRET=&lt;random-secret&gt; в среде рабочего сервера (и на всех клиентах, взаимодействующих с мостом)
  3. Перезапустите OmniRoute

Responses API: фоновый режим заменён синхронным

Заголовок раздела «Responses API: фоновый режим заменён синхронным»

Симптомы:

  • В журнал записывается предупреждение: background mode degraded to synchronous
  • Запрос с background: true возвращает обычный синхронный ответ вместо дескриптора фоновой задачи

Причина: В v3.8.0 запросы Responses API с background: true намеренно выполняются синхронно с выводом предупреждения. Полноценное асинхронное фоновое выполнение будет реализовано в будущем.

Исправление:

  • Измените клиент так, чтобы он выполнял вызов без background, или
  • Дождитесь более позднего выпуска с полноценным асинхронным фоновым режимом (следите за журналом изменений)

Если CLI выводит ⚠ Server did not respond within 60s, но сервер на самом деле работает, значит время ожидания проверки готовности слишком мало для вашей среды.

Такое часто происходит в Windows (из-за антивируса, наблюдателей за файловой системой) или в контейнерах с большой нагрузкой при запуске.

Решение — увеличьте время ожидания:

Окно терминала
# Через переменную среды (сохраняется между запусками):
export OMNIROUTE_READY_TIMEOUT_MS=180000 # 3 минуты
omniroute serve
# Через флаг CLI (однократно):
omniroute serve --ready-timeout 180000

Значение по умолчанию — 60 000 мс (60 с). Предупреждение носит исключительно информационный характер; сервер продолжает запускаться в фоновом режиме и станет доступен после завершения загрузки.

Полную информацию об OMNIROUTE_READY_TIMEOUT_MS см. в docs/reference/ENVIRONMENT.md.


  • Проблемы на GitHub: github.com/diegosouzapw/OmniRoute/issues
  • Архитектура: внутренние сведения см. в docs/architecture/ARCHITECTURE.md
  • Справочник API: описание всех конечных точек см. в docs/reference/API_REFERENCE.md
  • Панель мониторинга состояния: актуальное состояние системы доступно в разделе Dashboard → Health
  • Переводчик: используйте Dashboard → Translator для диагностики проблем с форматами

Исходный код OmniRoute (a58000c7685f)

HagiCode

HagiCode — агентная среда разработки со структурированными процессами, параллельным выполнением несколькими агентами и интерфейсами Hero Dungeon.

Превращайте идеи в полезное ПО с более умным, быстрым и увлекательным агентным рабочим процессом.

Главный экран HagiCode в светлой теме
  • SmartСтруктурированные процессы превращают намерение в исполнимый путь от идеи до готового изменения.
  • EfficientМультиагентные процессы параллельно продвигают исследование, реализацию и проверку.
  • FunHero Dungeon делает длительную совместную разработку наглядной и увлекательной.
Перейти на HagiCode