#gateway connect failed: Error: pairing required

1 messages · Page 1 of 1 (latest)

buoyant leafBOT
#

To help others find answers, you can mark your question as solved via Right click solution message -> Apps -> ✅ Mark Solution

tepid relic
#

@sly dome are you working?

#

Can display openclaw devices list in terminal

openclaw devices list

🦞 OpenClaw 2026.2.19-2 (45d9b20) — Type the command with confidence—nature will provide the stack trace if needed.


gateway connect failed: Error: pairing required

[openclaw] Failed to start CLI: Error: gateway closed (1008): pairing required
Gateway target: ws://127.0.0.1:18789
Source: local loopback
Config: /home/xxxxxxxxxx/.openclaw/openclaw.json
Bind: loopback
at Object.onClose (file:///home/xxxxx/.npm-global/lib/node_modules/openclaw/dist/call-DZzTR0NL.js:438:10)
at WebSocket.<anonymous> (file:///home/xxxxx/.npm-global/lib/node_modules/openclaw/dist/client-DoSZFvf3.js:1538:23)
at WebSocket.emit (node:events:519:28)
at WebSocket.emitClose (/home/xxxxx/.npm-global/lib/node_modules/openclaw/node_modules/ws/lib/websocket.js:273:10)
at Socket.socketOnClose (/home/xxxxx/.npm-global/lib/node_modules/openclaw/node_modules/ws/lib/websocket.js:1346:15)
at Socket.emit (node:events:519:28)
at TCP.<anonymous> (node:net:346:12)

even tho this morning everything was good

Im self hosting and on tailscale. Also I got this error

✓ Config: /home/syvala/.openclaw/openclaw.json
✓ Restart sentinel: none
! Port 18789
Port 18789 is already in use.

pid 3219839 xxxxxxx: openclaw-gateway (127.0.0.1:18789)
Gateway already running locally. Stop it (openclaw gateway stop) or use a different port.
✓ Tailscale: serve · Running · xxxxxxx.tailxxxxxxxx.ts.net
ips: xxxxxxxxxx
https: https://xxxxxxx.tailxxxxxxxx.ts.net/openclaw
✓ Skills: 73 eligible · 0 missing · /home/xxxxxxxx/.openclaw/workspace
! Channel issues skipped (gateway unreachable)

Gateway health:
connect failed: pairing required

sly domeBOT
#

pairing required here is device pairing (Control UI / CLI / nodes). The gateway is reachable, but it’s refusing the WS handshake because the connecting “device id” hasn’t been approved yet.

Fix (approve the pending device)

Run this on the same machine that’s running the gateway (SSH into it if needed):

# (optional) sanity: confirm which config the running service uses
openclaw gateway status

# list pending device pairing requests
openclaw devices list

# approve the browser/device shown as pending
openclaw devices approve <requestId>

Docs: https://docs.openclaw.ai/web/control-ui (see “Device pairing”) and https://docs.openclaw.ai/cli/devices

#

If openclaw devices list also fails with pairing required

That usually means you’re not actually hitting the gateway as a “local” client (common causes: connecting via a proxy/Serve URL, using a different profile/state dir than the running service, or a reverse proxy injecting x-forwarded-for).

Try forcing a direct loopback connect and the gateway token (don’t paste the token in this thread):

openclaw config get gateway.auth.token
openclaw devices list --url ws://127.0.0.1:18789 --token <token>

If openclaw gateway status shows a different Config (service) path than your CLI is using, re-run the commands with the same --profile <name> (or the same OPENCLAW_CONFIG_PATH/OPENCLAW_STATE_DIR) as the service.

Also: the “Port 18789 already in use” part is expected if the gateway is already running; it’s not the root problem.

If you paste openclaw gateway status (redact tokens), I can tell which of the above cases you’re in.

#

Yep — I’m here and working.

If you’re still stuck on the pairing required issue: did openclaw devices list show a pending request, and were you able to openclaw devices approve <requestId>?

young gyro
#

I’m having the same issue
When I run OpenClaw devices list it does not show a pending request, just error pairing required

sly domeBOT
#

If openclaw devices list itself immediately errors with pairing required, that means the CLI device you’re connecting from is being treated as a remote device, and the gateway is refusing the WS handshake until some already-approved operator device approves it.

The catch: only “local” connects are auto-approved (loopback / same-host). So the fix is to do the approval from the gateway host.

1) Run the devices command on the gateway host via loopback

SSH into the box that runs the gateway, then:

openclaw gateway status
openclaw config get gateway.auth.token # don’t paste the token here
openclaw devices list --url ws://127.0.0.1:18789 --token <token>

Now you should see pending requests, and you can:

#
openclaw devices approve <requestId>

Docs: https://docs.openclaw.ai/web/control-ui#device-pairing-first-connection

2) If you can’t SSH, use an SSH tunnel to make it “local”

From your laptop:

ssh -L 18789:127.0.0.1:18789 user@<gateway-host>

Then in your browser open http://127.0.0.1:18789/ and/or run the openclaw devices ... --url ws://127.0.0.1:18789 commands in another terminal (still while the tunnel is up).

3) Common reason this happens “suddenly”

You were previously connecting “locally”, but now your CLI/UI is connecting via a Tailnet/Serve URL (non-local) or you switched profiles/state dirs, so the gateway sees you as a brand new device again.

#

If you paste the output of openclaw gateway status (redact tokens), I can tell if you’ve got a profile/config mismatch.

tepid relic
sly domeBOT
#

Pulled your pastebin — key detail: you’re getting gateway closed (1008): pairing required even when connecting to ws://127.0.0.1:18789 with the correct token.

On loopback, that should be auto-approved, so when it isn’t, it’s almost always one of these:

  1. the gateway can’t read/write the device pairing store (~/.openclaw/devices/*) due to permissions/ownership, or
  2. the device store is corrupted / from an older install (you also have a clawdbot-gateway.service detected), and the gateway is failing its “local auto-approve” write.

A) Check/fix permissions (most common)

Run on the gateway host:

ls -la ~/.openclaw ~/.openclaw/devices || true

If you see anything in ~/.openclaw owned by root (often happens after running sudo openclaw ... once), fix it:

#
sudo chown -R "$USER:$USER" ~/.openclaw
openclaw gateway restart

Then retry:

openclaw devices list

B) Reset the device pairing store (safe “factory reset” for pairing)

This only resets paired devices, not your whole config.

openclaw gateway stop
#
mv ~/.openclaw/devices ~/.openclaw/devices.bak.$(date +%s)
openclaw gateway start

Then:

openclaw devices list

C) If you had an old gateway service running, stop it

This is optional, but since your status output detects it:

systemctl --user disable --now clawdbot-gateway.service || true
#
openclaw gateway restart

If it still fails

Please paste the relevant lines from the gateway file log (this won’t require the WS handshake):

tail -n 200 /tmp/openclaw/openclaw-2026-02-20.log | grep -Ei "pair|device|EACCES|EPERM|error"

That’ll tell us immediately if it’s a write/parse failure in ~/.openclaw/devices/*.json.

tepid relic
sly domeBOT
#

Got it — this paste is super useful.

What your log proves

The gateway is successfully receiving the WS connect, but it’s rejecting it with:

  • cause: "pairing-required"
  • reason: "not-paired"
  • remote=127.0.0.1
  • and it even generated a requestId.

So device pairing is working, but the local auto-approve isn’t triggering. In the gateway code, auto-approve only happens when the request is classified as a “local direct request”. If it’s not classified as local, the gateway always closes with pairing required.

That “local direct” check fails if the request has proxy headers (especially x-forwarded-host / x-real-ip / x-forwarded-for) from an address the gateway does not consider a trusted proxy.

1) Check if you’re hitting that proxy-header case

Run:

#
grep -Ei "Proxy headers detected|Loopback connection with non-local Host header" /tmp/openclaw/openclaw-2026-02-20.log | tail -n 50

If you see either warning, that’s the explanation for why loopback isn’t being treated as “local”.

2) Quick fix (safe for loopback bind): trust localhost as a proxy

Add this to your ~/.openclaw/openclaw.json:

{
gateway: {
trustedProxies: ["127.0.0.1", "::1"],
},
}
#

Then:

openclaw gateway restart
openclaw devices list

3) If it still doesn’t work: paste these two outputs

These don’t require gateway WS access:

openclaw config get gateway.trustedProxies
openclaw config get gateway.bind

And also (after one failed openclaw devices list attempt), paste the contents of:

#
cat ~/.openclaw/devices/pending.json

(redact nothing except if you feel it contains secrets; it shouldn’t—this is just device/publicKey metadata + requestId).

echo heron
#

hanz@hanz-pc:~$ openclaw status --all

🦞 OpenClaw 2026.2.19-2 (45d9b20) — WhatsApp automation without the "please accept our new privacy policy".


gateway connect failed: Error: pairing required
gateway connect failed: Error: pairing required
OpenClaw status --all

Overview
┌─────────────────┬───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┐
│ Item │ Value │
├─────────────────┼────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────

tepid relic
#

So still same issue xddd

echo heron
#

───┤
│ Version │ 2026.2.19-2 │
│ OS │ linux 6.8.0-100-generic (x64) │
│ Node │ 22.22.0 │
│ Config │ ~/.openclaw/openclaw.json │
│ Dashboard │ http://127.0.0.1:18789/

#

but openclaw is ansering

tepid relic
#

For me it was answering also before. But cron with telegram was damaged and wasnt able to send

echo heron
#

ok, i said claw to make a diagnosis and cheack for errors

sly domeBOT
#

That can be totally normal.

pairing required in your logs is device pairing for an operator client (CLI / Control UI / node) trying to connect to the Gateway WebSocket.

Your bot “answering” (Telegram/Discord/etc) means:

  • the Gateway process is running, and
  • your messaging channel is already authorized/paired (DM allowlist/pairing), so it can still process incoming chats.

It’s basically: the bot can talk to users, but you (as an operator device) are locked out of the control plane until that operator device is paired/approved.

If you tell me which surface you mean by “answering” (Discord channel? Telegram DM?) and whether your problem is specifically “CLI + dashboard can’t connect”, I can point to the exact approval step.

tepid relic
#

@sly dome how do I auth gateway? Bcs I still get pairing required and cant use gateway

sly domeBOT
#

Thanks — this paste confirms it’s not a filesystem permission issue anymore.

The important line is:

handshake:"failed" … cause:"pairing-required" … remote=127.0.0.1 … host=127.0.0.1:18789 … reason:"not-paired"

That means the gateway is treating your loopback WS connection as “not local”, so it’s not doing the silent auto-approve, and you get stuck in a pairing loop.

In practice this happens when the gateway sees any x-forwarded-* / proxy-style headers and you haven’t configured gateway.trustedProxies (even if the TCP connection is from 127.0.0.1).

Fix: trust loopback as a proxy (so local detection works)

Run on the gateway host:

openclaw config set gateway.trustedProxies --json '["127.0.0.1","::1"]'
openclaw gateway restart
#
openclaw devices list

After that, openclaw devices list should finally work (and/or auto-approve the local CLI device).

If it STILL says pairing required

Do this grep and paste the output:

grep -Ei "Proxy headers detected|Loopback connection with non-local Host header" /tmp/openclaw/openclaw-2026-02-20.log | tail -n 50

(Those warnings are exactly what decides “local vs remote” for auto-pairing.)

Re: your Telegram cron not sending — yeah, that can happen even while the bot still replies normally; but we need CLI/operator access back first so we can inspect openclaw cron list + run history and channel probe.

#

Gateway auth (token/password) and device pairing are two separate gates:

1) “How do I auth the gateway?”

On the gateway host:

  • Your token is gateway.auth.token:
openclaw config get gateway.auth.token
  • Control UI: run
openclaw dashboard --no-open

Open the printed URL, then in the Control UI settings paste the Gateway Token (there’s also a password field if you use password auth).

  • CLI: pass it explicitly:
#
openclaw devices list --url ws://127.0.0.1:18789 --token <TOKEN>

2) Why you still get pairing required even with the token

pairing required is device pairing: the gateway is saying “I see your deviceId, but it’s not approved yet”.

Normally, true localhost/loopback gets auto-approved. In your log, it isn’t auto-approving, so you end up locked out.

Fix A (recommended): restore correct “local” detection

Set trusted proxies for loopback and restart:

openclaw config set gateway.trustedProxies --json '["127.0.0.1","::1"]'
openclaw gateway restart
openclaw devices list
#

Fix B (break-glass): temporarily disable Control UI device auth, then approve

If you’re totally locked out and need a way back in:

  1. Set (temporarily):
openclaw config set gateway.controlUi.dangerouslyDisableDeviceAuth true
openclaw gateway restart
  1. Open the dashboard, auth with token, go to Devices, approve the pending request(s).

  2. Turn it back off:

openclaw config unset gateway.controlUi.dangerouslyDisableDeviceAuth
openclaw gateway restart
#

This is a security downgrade, so only use it to recover access, then revert immediately.

After you’re back in (Telegram cron “damaged”)

Once openclaw devices list works again, run:

openclaw cron list
openclaw cron status
openclaw channels status --probe

and we can debug why Telegram cron deliveries stopped.

tepid relic
#

Can I refresh that gateway.auth.token? I think its broken and thats why I cant connect

sly domeBOT
#

You can rotate gateway.auth.token, but it won’t fix pairing required. That error is device pairing, not “bad token”. If the token were wrong you’d see unauthorized: gateway token mismatch/missing, not pairing required.

That said, if you want to rotate it anyway (this will invalidate the old token everywhere):

Rotate token (recommended way)

On the gateway host:

openclaw config set gateway.auth.token "$(openssl rand -hex 32)"
openclaw gateway restart

Then update anywhere you’ve saved the token:

  • Control UI settings (Gateway Token field)
  • any remote CLI configs (gateway.remote.token) or scripts using --token

Note

#

openclaw doctor --generate-gateway-token only generates one if missing; it does not rotate an existing token.

If you paste the output of:

openclaw config get gateway.trustedProxies

I can confirm whether you’re hitting the proxy-header/local-detection issue that causes the pairing loop.

tepid relic
#

openclaw config get gateway.trustedProxies

🦞 OpenClaw 2026.2.19-2 (45d9b20) — No $999 stand required.

[
"127.0.0.1",
"::1"
]

But I still get disconnected (1008): pairing required on gateway. Even after token rotate. How do I check if the token is set properly?

sly domeBOT
#

Your token is almost certainly set and working already — because if the token was wrong/missing you would get unauthorized: gateway token mismatch/missing, not pairing required.

How to verify the token is set properly (quick test)

Intentionally use a wrong token and confirm the error changes:

openclaw devices list --url ws://127.0.0.1:18789 --token WRONGTOKEN
  • If you see unauthorized: gateway token mismatch → token is definitely being enforced by the gateway.
  • If you still see pairing required even with a wrong token → something is very weird and we should look at the gateway logs immediately.

Why you’re blocked right now

pairing required = device pairing. Your CLI/Control UI “device” is not approved as an operator device yet (or it’s trying to “upgrade” role/scopes), and for some reason your gateway is not auto-approving localhost.

You already set:

#
gateway.trustedProxies: ["127.0.0.1","::1"]

…so the next step is a break-glass recovery to get an operator UI back in so you can approve devices.

Break-glass recovery (then revert)

  1. Temporarily disable Control UI device auth (token-only):
openclaw config set gateway.controlUi.dangerouslyDisableDeviceAuth true
openclaw gateway restart
  1. Open the dashboard locally and paste the gateway token in settings:
#

(or run openclaw dashboard --no-open)

  1. In Control UI → Devices: approve the pending request(s) (you should see one for the CLI).

  2. Re-enable normal security:

openclaw config unset gateway.controlUi.dangerouslyDisableDeviceAuth
openclaw gateway restart

One more useful datapoint

After one failed CLI connect, paste this (redact nothing; it shouldn’t contain secrets):

cat ~/.openclaw/devices/pending.json
#

That will confirm whether the gateway is creating the pending device request and whether it thinks it’s “silent/local” or not.

tepid relic
#

user@hostname:~/.openclaw$ openclaw devices list --url ws://127.0.0.1:18789 --token WRONGTOKEN

🦞 OpenClaw 2026.2.19-2 (45d9b20) — Automation with claws: minimal fuss, maximal pinch.


gateway connect failed: Error: unauthorized: device token mismatch (rotate/reissue device token)

[openclaw] Failed to start CLI: Error: gateway closed (1008): unauthorized: device token mismatch (rotate/reissue device token)
Gateway target: ws://127.0.0.1:18789
Source: cli --url
Config: /home/<user>/.openclaw/openclaw.json
at Object.onClose (file:///home/<user>/.npm-global/lib/node_modules/openclaw/dist/call-DZzTR0NL.js:438:10)
at WebSocket.<anonymous> (file:///home/<user>/.npm-global/lib/node_modules/openclaw/dist/client-DoSZFvf3.js:1538:23)
at WebSocket.emit (node:events:519:28)
at WebSocket.emitClose (/home/<user>/.npm-global/lib/node_modules/openclaw/node_modules/ws/lib/websocket.js:273:10)
at Socket.socketOnClose (/home/<user>/.npm-global/lib/node_modules/openclaw/node_modules/ws/lib/websocket.js:1346:15)
at Socket.emit (node:events:519:28)
at TCP.<anonymous> (node:net:346:12)

cat ~/.openclaw/devices/pending.json
{
"9dc3e592-7xxxxxxxxxxxxxxxxxxx": {
"requestId": "9dc3e592-7xxxxxxxxxxxxxxxxxxx",
"deviceId": "1cd3dc47f88de9xxxxxxxxxxxxxxxxxxx",
"publicKey": "5AyTC7qbvwbRoxxxxxxxxxxxxxxxxxxx",
"platform": "MacIntel",
"clientId": "openclaw-control-ui",
"clientMode": "webchat",
"role": "operator",
"roles": [
"operator"
],
"scopes": [
"operator.admin",
"operator.approvals",
"operator.pairing"
],
"remoteIp": "100.11xxxxxxxxxxxxxxxxxxx",
"silent": false,
"isRepair": false,
"ts": 1771602025660
}
}

#

@sly dome ?

young gyro
#

For the record, and i know im different then the person who opened this ticket, these steps finally solved this problem for me:

`A) Check/fix permissions (most common)
Run on the gateway host:

ls -la ~/.openclaw ~/.openclaw/devices || true

If you see anything in ~/.openclaw owned by root (often happens after running sudo openclaw ... once), fix it:
sudo chown -R "$USER:$USER" ~/.openclaw
openclaw gateway restart

Then retry:

openclaw devices list

B) Reset the device pairing store (safe “factory reset” for pairing)
This only resets paired devices, not your whole config.

openclaw gateway stop
mv ~/.openclaw/devices ~/.openclaw/devices.bak.$(date +%s)
openclaw gateway start

Then:

openclaw devices list`

sly domeBOT
#

Nice — thanks for posting the confirmed fix.

That matches what we see a lot: a single accidental sudo openclaw ... leaves parts of ~/.openclaw root-owned, and then device pairing can’t persist/upgrade cleanly, which cascades into disconnected (1008): pairing required.

If this solved it for you, please right-click the message with the solution → Apps → ✅ Mark Solution so Answer Overflow indexes it for the next person.

sly domeBOT
#

Good — that strongly suggests you had two gateway-ish things fighting (or a wedged gateway process holding bad state), and stopping the service cleared it.

To finish cleanly (so it doesn’t come back):

  1. Start it again and confirm health:
openclaw gateway start
openclaw gateway status
openclaw devices list
  1. If gateway status still shows “Other gateway-like services detected: clawdbot-gateway.service”, disable the old one so only one gateway runs:
systemctl --user disable --now clawdbot-gateway.service
openclaw gateway restart
#

If this fixed your thread, please mark the solution message (right-click → Apps → ✅ Mark Solution) so it gets indexed.

tepid relic
#

For me worked

openclaw gateway stop```

```bash
cat ~/.openclaw/devices/pending.json | python3 -c "
import json, sys
pending = json.load(sys.stdin)
paired = {}
for rid, device in pending.items():
    paired[device['deviceId']] = device
print(json.dumps(paired, indent=2))
" > ~/.openclaw/devices/paired.json
openclaw gateway restart```

but its still adding so weird stuff to devices/pending.json when I do 

```bash
openclaw devices list```

and still pulling that error, at least my gateway is working properly
sly domeBOT
#

That pending.json → paired.json copy hack is what’s biting you.

paired.json is not the same shape as pending.json: when you approve a device, the gateway generates device tokens and stores extra fields. If you just copy pending entries over, you end up with a “paired” device that still can’t authenticate properly → and the gateway will keep creating new pending requests and you’ll keep seeing pairing required.

Do this to get back to a clean state (no hacks)

On the gateway host:

openclaw gateway stop
mv ~/.openclaw/devices ~/.openclaw/devices.bak.$(date +%s)
openclaw gateway start

Now don’t edit those JSON files manually.

If you’re still locked out (break-glass to approve your operator device)

Temporarily bypass device identity for the Control UI only, so you can approve devices:

#
openclaw config set gateway.controlUi.dangerouslyDisableDeviceAuth true
openclaw gateway restart

Open: http://127.0.0.1:18789/openclaw/ (or openclaw dashboard --no-open) and paste your gateway token in settings, then go to Devices and approve the pending request(s).

Then immediately revert the break-glass setting:

openclaw config unset gateway.controlUi.dangerouslyDisableDeviceAuth
openclaw gateway restart

After that, this should stop producing pairing required: