«configuration is invalid» в sing-box: как понять причину и починить

Обновлено 2026-07-03

Коротко: sing-box отвергает конфиг целиком и пишет причину сразу после двоеточия — читать нужно именно этот кусок, там указан путь до проблемного поля. Пять самых частых поводов: битый JSON (лишняя запятая), отсутствующий default_domain_resolver (обязателен с 1.12), rule_set типа local ссылается на несуществующий .srs, поле переименовали при обновлении версии, два outbound с одинаковым tag. Проверять до запуска: sing-box check -c config.json.

Ошибка выглядит пугающе, но она из добрых: sing-box не запускается наполовину, а отказывается целиком и говорит, что именно ему не понравилось. Проблема только в том, что сообщение длинное и главное в нём — не первые слова, а то, что идёт после двоеточия.

Сначала прочитайте саму ошибку

Полное сообщение выглядит так: FATAL[0000] configuration is invalid: parse config: ... — и вот этот хвост после двоеточия и есть ответ. sing-box указывает путь до поля в JSON: например route.rules[3] или outbounds[1].tls. Считать индексы удобно, открыв конфиг в редакторе со сворачиванием блоков. Отдельно полезная команда: sing-box check -c config.json — она проверяет конфиг, ничего не запуская, и печатает ту же ошибку.

Причина 1: битый JSON

Самое частое и самое обидное — лишняя запятая перед закрывающей скобкой, незакрытая кавычка, комментарий в стиле // (в JSON их нет). Такой конфиг не доходит даже до проверки смысла. Признак: в ошибке будет упомянут символ или строка, а не имя поля. Лечится любым JSON-валидатором или тем же sing-box check.

Причина 2: нет default_domain_resolver (с версии 1.12)

Начиная с sing-box 1.12 в секции route обязателен default_domain_resolver — резолвер, который используется, когда домен нужно разрешить в момент установки соединения. Раньше это работало по умолчанию, теперь без явного указания конфиг отвергается. Добавьте в route: "default_domain_resolver": { "server": "remote" }, где remote — тег вашего DNS-сервера из секции dns. Это самая частая причина, по которой конфиг, работавший год назад, вдруг перестал запускаться после обновления.

Причина 3: rule_set ссылается на файл, которого нет

Если у вас { "type": "local", "path": "...srs" }, а файла по этому пути нет — отвергается весь конфиг, а не одно правило. Поэтому опасно ссылаться на .srs, который скачивается отдельно: не скачался — и тоннеля нет вообще. Надёжнее либо класть .srs рядом и проверять наличие перед запуском, либо продублировать логику обычным правилом domain_suffix, чтобы при пропаже rule_set маршрутизация деградировала, а не умирала.

Причина 4: поле переименовали при обновлении

sing-box меняет схему между минорными версиями чаще, чем хотелось бы. Классика: в правилах маршрутизации outbound в ряде случаев уступил место action, устаревшие формы записи DNS-серверов перестали приниматься. Если конфиг взят из статьи годичной давности, а бинарник свежий — сверьтесь с официальной документацией именно вашей версии: sing-box version покажет её.

Причина 5: дубли тегов

Два outbound с одинаковым tag — и конфиг невалиден. Легко получить, когда вручную склеиваешь ноды из нескольких подписок: имена совпадают. Ошибка укажет на дублирующийся тег.

Если разбираться не хочется

Всё вышеперечисленное — плата за ручную сборку конфига. Клиенты, которые собирают конфигурацию сами и обновляют её на лету, эту категорию проблем снимают: Orden построен на том же ядре sing-box (VLESS-Reality + Hysteria2 с автопереключением), конфиг генерируется под вашу версию, руками править нечего. Код открыт: github.com/tsyrenov1987/orden-android-client. Рабочий пример конфига с разбором граблей выложен отдельно: https://github.com/tsyrenov1987/orden-singbox-configs

Orden — VPN, который сам обновляется и переживает DPI

VLESS-Reality + Hysteria2, автопереключение, банки и Госуслуги работают напрямую. На устройстве, без логов, открытый код.

Открыть Orden →

Частые вопросы

Как узнать, в какой строке конфига ошибка?
sing-box указывает не строку, а путь до поля в JSON — например route.rules[3]. Откройте конфиг в редакторе, сверните блоки и отсчитайте элемент по индексу (нумерация с нуля). Команда sing-box check -c config.json выдаёт ту же ошибку, ничего не запуская.
Конфиг работал раньше, а после обновления перестал. Почему?
Чаще всего из-за схемы: с версии 1.12 обязателен default_domain_resolver в секции route, а часть полей маршрутизации была переименована. Сверьтесь с документацией именно вашей версии — её покажет sing-box version.
Можно ли проверить конфиг, не запуская тоннель?
Да: sing-box check -c config.json. Она разбирает и валидирует конфигурацию, но не поднимает интерфейс — удобно проверять правки до перезапуска сервиса.