Коротко

  • Это почти никогда не значит, что OpenClaw сломался. Gateway работает нормально. Просто твоего клиента — CLI, дашборд, ноду, чат-канал — ещё не авторизовали, чтобы с ним говорить. Соединение закрывается с кодом WebSocket 1008 и сообщением pairing required.
  • Быстрый фикс, когда причина `not-paired`: посмотри висящий запрос и одобри его.
openclaw devices list
openclaw devices approve <requestId>
  • Если одобрение не помогло, читай `reason`. OpenClaw прямо говорит, в каком из четырёх случаев ты оказался: not-paired, scope-upgrade, role-upgrade, metadata-upgrade. У каждого свой фикс, и «одобри устройство ещё раз» лечит только первый.
  • Держи в голове двойника. Расхождение токена (AUTH_TOKEN_MISMATCH) падает похоже, но это совершенно другая проблема, и команды пейринга её не трогают. Отличить одно от другого — половина дела.

Я пишу это не как документацию OpenClaw. Я держу OpenClaw и Hermes в проде, и «pairing required» — одна из ошибок, которую я ловил чаще всего и чаще всего диагностировал неправильно. Почти всё ниже — то, что я сначала делал не так, а потом разобрался. Задача — помочь тебе за пару минут понять, какой именно из случаев перед тобой, а не перегенерировать токены наугад, пока что-нибудь не сработает.

Что на самом деле значит «pairing required»

Когда клиент подключается к gateway, он предъявляет идентичность устройства — ключ, который gateway должен был одобрить заранее. Если этого ключа нет в списке одобренных, gateway отказывает в соединении, закрывает сокет с кодом 1008 и присылает сообщение, начинающееся с pairing required. Твой CLI заворачивает это в строку, которую ты и видишь:

gateway connect failed: pairing required

Читай её буквально: она говорит правду. connect failed — это клиент говорит «я не смог войти». pairing required — это сервер говорит «я не узнаю это устройство». Ни то, ни другое не говорит, что gateway лежит, конфиг битый или токен неверный. Gateway ответил. Просто ответил «нет».

Полезное — в поле reason, которое gateway прикладывает. Их четыре, и они не взаимозаменяемы:

  • `not-paired` — это устройство никогда не одобряли. Первый раз на этой машине, или идентичность сбросили.
  • `scope-upgrade` — устройство одобрено, но просит прав больше, чем ему выдали.
  • `role-upgrade` — одобрено, но просит действовать в роли выше, чем ему дали.
  • `metadata-upgrade` — одобрено, но запрашивает смену своих зарегистрированных метаданных.

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

Быстрый фикс: одобрить висящий запрос

Начинай отсюда: это частый случай, и он правда простой. Когда неузнанное устройство пытается подключиться, gateway его не просто отвергает. Он заводит висящий запрос на пейринг и ждёт, пока оператор его одобрит. Оператор — это ты.

openclaw devices list

Это покажет висящие запросы, у каждого есть request ID. Найди свой (если ты только что вызвал ошибку — это свежий) и одобри:

openclaw devices approve <requestId>

Дальше переподключись. Клиент, которому отказали, теперь получит токен устройства, сохранит его и переподключится уже авторизованным. В чат-каналах есть аналог: оператор с правом на пейринг может одобрить запрос устройства из чата, а интеграция с Telegram выводит висящий запрос на одобрение в своём флоу.

Тут спотыкаются на двух вещах. Первое: request ID — это не device ID, это разные значения, и если скопировать не то, получишь unknown requestId. Второе: на свежей машине висящий запрос существует, только если клиент реально достучался до gateway и объявил себя. Если запрос не создался (почему так бывает с удалёнными gateway — ниже), одобрять нечего, и ты будешь одобрять пустоту, недоумевая, почему ничего не меняется.

Ещё одна развилка, которую стоит знать, прежде чем копать глубже. Эта статья — про то, что отказывают клиенту: CLI, дашборду, ноде. Если же отказывают чат-отправителю (ты написал боту в Telegram, а он не отвечает) — это другая система: пейринг канала, а не устройства, со своими командами. Такого одобряют через openclaw pairing list --channel telegram, потом openclaw pairing approve telegram <code>, а не devices approve.

Когда одобрения мало: scope и role

Вот этот случай стоил мне больше всего времени, потому что симптом врёт. Всё говорит, что устройство спарено. Оно подключается. А потом конкретная операция всё равно падает с pairing required, reason: scope-upgrade.

Форма такая. Устройство одобрили один раз, рано, под узкий набор прав — скажем, read-only, потому что первое, что оно сделало, — прочитало какой-то статус. Позже от него требуется больше: запустить задачу по расписанию, записать изменение в конфиг, действовать с админ-правами. Gateway смотрит на запрос, видит, что устройство просит прав сверх тех, что у него есть, и вместо того чтобы тихо повысить (а это была бы дыра в безопасности), отвечает запросом на апгрейд scope, который надо одобрить. Пока кто-то не одобрит, операция просто падает, и падает ошибкой из семейства «pairing required», хотя устройство вот оно, спарено.

Я сжёг на этом ровно один вечер. Одна backend-идентичность была зафиксирована на read-only scope при первом же вызове, и каждое последующее админ-действие — задача по расписанию, запись конфига — возвращалось как «scope upgrade pending approval» вместо того, чтобы выполниться. Я раз за разом переодобрял устройство, которое и так было одобрено, потому что не прочитал reason. Дело было никогда не в устройстве. Дело было в scope.

Фикс — одобрить повышенный scope, а не перепаривать с нуля. Посмотри, что реально нужно падающей операции: токен спаренного устройства может управлять только своим устройством, если у вызывающего нет админ-scope. Если твоей автоматизации нужно больше, устройству надо осознанно выдать больше, а потом одобрить апгрейд. Перепаривание даст тебе свежее устройство с тем же узким scope и той же ошибкой.

Двойник: расхождение токена — это не про пейринг

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

Пейринг — это про то, какому устройству разрешено подключаться. Ещё у gateway есть обычный общий auth-токен, и это отдельный барьер. Если токен, который предъявил клиент, не совпадает с тем, что ждёт gateway, ты получаешь AUTH_TOKEN_MISMATCH, а не PAIRING_REQUIRED. То же смутное ощущение «не подключается», причина другая, и openclaw devices approve тут ничего не даст: падение не в пейринге, и висящего запроса, который можно одобрить, просто нет. Устройство может быть прекрасно спарено. Неверен токен.

По-настоящему коварно становится там, где речь про то, откуда токен читается. Gateway-сервис читает его из конфига в первую очередь — из gateway.auth.token в ~/.openclaw/openclaw.json. Локальный CLI-клиент читает из окружения в первую очередь — из OPENCLAW_GATEWAY_TOKEN. На одной машине эти двое могут разойтись: ты выставил переменную окружения, уверен, что токен «задан», а работающий gateway сверяет с другим значением из конфиг-файла. Всё говорит, что токен есть. Просто это не один и тот же токен.

Про сторону «откуда токен берётся» я подробнее написал в чек-листе по безопасности OpenClaw; здесь мысль уже и диагностическая. Прежде чем вообще трогать пейринг, посмотри код ошибки. Если там расхождение токена или 401 с отсутствующим либо неверным bearer-токеном — стоп, это не пейринг, и никакие devices approve его не починят. Выясни, из какого источника gateway реально читает токен, и приведи оба к одному значению. Если там, где должен быть токен, стоит строка вроде secretref-env:VAR_NAME или $VAR — это ссылка на переменную окружения, а не сам токен; если переменная не выставлена, токена по факту нет.

Почему это почти всегда удалённый gateway

Если «pairing required» вылезает ровно в тот момент, когда ты направляешь клиента на gateway через Tailscale, VPN или на другой хост, — это не совпадение, и понимание причины закрывает целый класс путаницы.

OpenClaw относится к клиенту на той же машине, что и gateway, иначе, чем к клиенту, приходящему по сети. Локальному клиенту — на loopback или доверенном адресе — можно разрешить спариться молча: gateway доверяет собственному хосту. Удалённому — по умолчанию нельзя. Его надо одобрить явно, один раз на идентичность устройства, by design (оператор может опционально авто-одобрять конкретные доверенные удалённые сети, но это осознанный выбор, а не дефолт). Поэтому та же установка, что «просто работала» локально, начинает требовать одобрения, стоит перенести клиента на другую коробку. Ничего не сломалось. Ты пересёк границу, за которой тихий локальный пейринг больше не действует.

Есть и вторая, чисто удалённая ловушка. Когда подключаешься к удалённому gateway, CLI иногда не может сам сгенерировать идентичность устройства, а значит, и не заводит висящий запрос. А если запроса нет, то и одобрять нечего. Ты сидишь и гоняешь openclaw devices approve по пустому списку. Фикс — дать клиенту явную идентичность, чтобы он создал нормальный запрос. Для ноды это openclaw node run с --node-id и --display-name; потом одобри запрос, который появится.

И знай свой режим. У OpenClaw есть настройка gateway.mode с двумя значениями — local и remote. local значит, что CLI может поднять и говорить с gateway на этой машине; remote — что он целится в gateway где-то ещё и локальный поднимать не будет. Я однажды по ошибке вписал remote в конфиг на одно-хостовой коробке, и локальный gateway просто отказался стартовать: режим remote ровно это и отключает. Если у тебя всё на одной машине, тебе нужен local. Если целишься в другой хост — remote с правильным gateway.remote.url. Перепутать местами — получить отказы подключения, которые не имеют отношения к пейрингу и целиком про то, что клиент ищет gateway не там.

«Connect failed» сразу после рестарта или обновления

Ещё один источник ложных тревог, и это проблема тайминга, а не авторизации. Сразу после того, как gateway перезапустился — включая перезапуск, который обновление или смена конфига запускает сами по себе, — есть окно, где клиенты получают «connect failed». Это не всегда пейринг. Иногда gateway просто ещё не готов.

Gateway может подниматься ощутимое число секунд. Я видел, как боевой поднимался около восемнадцати. Клиент, который пытается подключиться в этом окне, или bootstrap-шаг, который стреляет командой в gateway посреди рестарта, получает отказ, который выглядит тревожно и не значит ничего: подожди, повтори — всё нормально. У меня job'ы обновления рапортовали об ошибке ровно по этой причине — команда отвалилась по таймауту, потому что совпала с рестартом, который сама же смена конфига и вызвала, — при том что новая версия всё это время была установлена и здорова.

Разница, которую стоит усвоить: часть отказов подключения стоит ретраить, а часть — нет. Холодный старт или временная заминка протокола ретраятся: дай несколько секунд, и пройдёт. Отказ по авторизации, устройству или scope — нет; крутить pairing required в цикле бесполезно, устройство от этого не одобрится, и я видел, как клиент висел «offline» вечно после апгрейда, потому что счёл несовпадение версий постоянным и больше не перепроверял. Так что: если отказ появился ровно в момент рестарта или обновления — дождись, пока gateway отрапортует «здоров», и повтори, прежде чем что-то трогать. Если он держится после того, как gateway поднялся, — вот тогда читай reason и относись к нему всерьёз.

«Записано» — не значит «применено»

Коротко, но на этом попадаются. Ты меняешь auth-конфиг или ротируешь токен, файл записывается корректно, а работающий gateway продолжает применять старое значение. Записано — не то же, что действует. Живой gateway держит собственное представление о конфиге, и простая запись не всегда до него доходит; изменение вступает в силу, когда gateway перечитает конфиг или перезапустится и пересоберёт своё состояние из файла.

С проблемой «конфиг не применяется» я однажды столкнулся и с другого конца — через умерший config-watcher, о чём написал в чек-листе по безопасности. Урок тот же, повод другой: после того как поменял что-то, связанное с авторизацией, сверься с живым gateway, а не с тем фактом, что файл сохранился. Иначе «починишь» токен, увидишь, что файл обновился, и будешь смотреть на ту же ошибку, потому что gateway её не подхватил.

Как быстро отличить одно от другого

Когда видишь отказ подключения, не гадай. Прочитай ошибку и пройди по ней:

  • `pairing required`, reason `not-paired` → устройство неизвестно. openclaw devices list, потом openclaw devices approve <requestId>. Переподключись.
  • `pairing required`, reason `scope-upgrade` / `role-upgrade` → устройство известно, но прав мало. Одобри апгрейд или выдай scope, который нужен операции. Не перепаривай.
  • `AUTH_TOKEN_MISMATCH` или `401` по bearer-токену → это не пейринг. Чини токен и проверь, откуда gateway его читает — из конфига или из окружения.
  • Connect failed ровно в момент рестарта или обновления → скорее всего холодный старт. Дождись «здоров», повтори, потом перечитай.
  • Несовпадение `gateway.mode` → локальный клиент с remote (или наоборот). Сначала почини режим.

Чаще всего тридцать секунд с реальным текстом ошибки бьют час попыток наугад. openclaw doctor и openclaw doctor --fix тоже стоит прогнать — доктор ловит несколько из перечисленных ошибок конфига и источника токена автоматически, — но запускай его после того, как прочитал reason, чтобы понимать, починил он твой случай или какой-то другой.

Чего это не расскажет

Скажу честно про края. Здесь разобраны отказы, которые я реально ловил, а это не все возможные. Если ты прочитал reason, там правда not-paired, ты одобрил запрос, режим правильный, токен совпадает, gateway поднят и здоров — а оно всё равно не подключается, — значит, ты вышел за пределы частых причин и попал во что-то более специфичное: несовместимость версий клиента и gateway, сломанный WebSocket-транспорт, reverse-proxy перед gateway, калечащий handshake (прокси, которые режут по параметру ?token= в адресе, ломают его, потому что настоящий токен едет внутри handshake после открытия сокета, а не в URL), конфликт портов или настоящий баг. На этом этапе список висящих запросов и код reason сказали тебе всё, что могли, и дальше — логи gateway и, если воспроизводится, issue в апстрим.

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

Если не хочется гоняться за этим каждый релиз

Всё вышеописанное управляемо, когда увидел это несколько раз. Изматывает то, что оно возвращается: OpenClaw выпускает обновления, обвязка токена или состояние пейринга могут поехать под одним из них, и каждый апгрейд — очередной шанс потратить вечер на 1008. Это та часть, которую я делаю, чтобы о ней не думать, и это по большей части и есть Cain. Что здесь важно: новую версию валидируют против upgrade-matrix, прежде чем разрешить к раскатке, так что регрессия пейринга или токена — это как раз то, что ловится до того, как доедет до выделенного под тебя сервера. Фиксы безопасности всё равно доходят, просто без чужой регрессии в довесок. OpenClaw и Hermes он держит на этом же сервере, один клиент на сервер. Это один из вариантов, а не единственно верный ответ. Если тебе норм держать это самому, шаги выше — это те, по которым я бы и шёл.

FAQ

Что значит «openclaw gateway connect failed: pairing required»? Gateway работает, но идентичность устройства твоего клиента не одобрена (или одобрена, но просит прав больше, чем ей выдали), поэтому соединение отклоняется с кодом WebSocket 1008. Это шаг авторизации, а не падение. Прочитай reason, потом одобри устройство или апгрейд и переподключись.

Как одобрить запрос на пейринг в OpenClaw? Выполни openclaw devices list, чтобы увидеть висящие запросы, потом openclaw devices approve <requestId> с ID твоего. В чат-каналах оператор с правом на пейринг может одобрить запрос прямо из канала. После этого переподключись.

Почему «pairing required» вылезает только на удалённом или Tailscale-gateway? Потому что по умолчанию удалённый клиент не может спариться молча — это могут только локальные, на доверенном адресе. Установка, работавшая локально, потребует явного одобрения, стоит клиенту оказаться на другом хосте. Для ноды дай ей явную идентичность (openclaw node run --node-id <id> --display-name <name>), чтобы она завела запрос, который ты одобришь.

В чём разница между «pairing required» и расхождением токена? Пейринг — про то, какому устройству разрешено подключаться; токен — отдельный общий секрет. pairing required (1008) чинится одобрением устройства; AUTH_TOKEN_MISMATCH — приведением токена клиента к токену gateway. Команды пейринга ничего не дают для проблемы с токеном и наоборот. Сначала смотри код ошибки.

Откуда OpenClaw читает auth-токен gateway? Gateway-сервис читает его из конфига в первую очередь — из gateway.auth.token в ~/.openclaw/openclaw.json, — а как запасной вариант берёт переменную окружения OPENCLAW_GATEWAY_TOKEN. Локальный CLI предпочитает переменную окружения. Если эти два источника расходятся на одной машине, gateway может отклонить токен, который ты считаешь «заданным».

Как починить «scope upgrade pending approval» (ошибка 1008)? Эта причина значит, что устройство уже спарено, но запрашивает прав больше, чем у него есть. Одобри апгрейд scope или выдай устройству scope, который нужен операции, — не перепаривай, это лишь даст свежее устройство с теми же узкими правами.

Чинит ли `openclaw doctor --fix` «pairing required»? Он чинит несколько проблем конфига и источника токена, которые выглядят как отказы пейринга, — это полезно. Но он не заменяет одобрение по-настоящему неспаренного устройства: при reason not-paired запрос всё равно одобряешь ты. Сначала прочитай reason, потом дай доктору разобраться с конфигом.

Как безопасно перезапустить gateway OpenClaw? Перезапусти его через openclaw gateway restart, а потом дождись, пока он отрапортует «здоров» (openclaw gateway status), прежде чем переподключаться или гнать в него команды: gateway посреди рестарта возвращает отказы подключения, которые проходят сами. Если рестарт вызвала смена конфига или токена, сверь изменение с живым gateway после того, как он поднялся, а не только с сохранённым файлом.

Илья Прудников держит приватные развёртывания OpenClaw и Hermes. Это полевые заметки оператора об одной конкретной ошибке, а не официальная документация OpenClaw; в спорных местах источник истины — доки самого проекта.