#Pairing issues
1 messages · Page 1 of 1 (latest)
That message is the Control UI browser device not being approved yet (common with Docker/Podman because the Gateway sees your browser as a “remote” IP, not 127.0.0.1).
Fix: approve the pending device on the Gateway
On the machine where the Gateway is running:
openclaw devices list
openclaw devices approve <requestId>
Then refresh the dashboard tab.
If you’re running the containerized (Podman) setup
Run the same commands via the CLI container (use whichever compose wrapper you used):
podman compose run --rm openclaw-cli devices list
podman compose run --rm openclaw-cli devices approve <requestId>
(Equivalent in the docs uses docker compose ....)
If you also need a fresh dashboard link/token:
podman compose run --rm openclaw-cli dashboard --no-open
Quick note (because OpenClaw has 2 “pairing” concepts)
- Control UI / nodes pairing =
openclaw devices ...âś… (this is your error) - DM sender pairing (who can message the bot) =
openclaw pairing ...
Docs: https://docs.openclaw.ai/web/control-ui (Device pairing section) and https://docs.openclaw.ai/gateway/pairing
If devices list shows nothing pending, paste openclaw --version + how you’re launching the Podman setup (compose command + ports), and we can pinpoint why the request isn’t being created.
@balmy verge Okay, some additional info: I did the openclaw account setup from here https://docs.openclaw.ai/install/podman . My podman container is running for the openclaw user. I'm currently working from my normal account that is not the openclaw one.
Yep — with the Podman rootless setup this is expected:
- the Gateway is running under the
openclawLinux user - rootless Podman is effectively per-user, so from your normal account you often can’t see / control the
openclawuser’s containers (and you’ll be looking at the wrong state dir too)
That “disconnected (1008): pairing required” in the dashboard is Control UI device pairing (not DM pairing). You need to approve the browser device from the gateway side, i.e. as the openclaw user.
Approve the pending Control UI device (Podman user = openclaw)
- First, confirm the container name:
sudo -u openclaw podman ps
- Then run the devices commands inside the running gateway container (this reuses the token env the container already has):
sudo -u openclaw podman exec -it openclaw bash -lc \
'node dist/index.js devices list --url ws://127.0.0.1:18789 --token "$OPENCLAW_GATEWAY_TOKEN"'
sudo -u openclaw podman exec -it openclaw bash -lc \
'node dist/index.js devices approve <requestId> --url ws://127.0.0.1:18789 --token "$OPENCLAW_GATEWAY_TOKEN"'
After approving, refresh the dashboard tab and it should connect.
Why this matters
Each browser profile gets a unique device ID, and in the Podman guide remote/non-loopback connections require explicit approval. Also, doing this from your normal user usually fails because it’s a different rootless Podman “world”.
Docs reference: https://docs.openclaw.ai/web/control-ui (Device pairing section) and https://docs.openclaw.ai/install/podman
If sudo -u openclaw podman ps doesn’t show a container named openclaw, paste that output and I’ll tell you the exact podman exec ... line for the right container name.
@balmy verge sudo -u openclaw podman ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
710538dfe38a localhost/openclaw:local node dist/index.j... 52 minutes ago Up 52 minutes 0.0.0.0:18789-18790->18789-18790/tcp openclaw
and
sudo -u openclaw podman exec -it openclaw bash -lc 'node dist/index.js devices list --url ws://127.0.0.1:18789 --token "$OPENCLAW_GATEWAY_TOKEN"'
[openclaw] CLI failed: 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/node/.openclaw/openclaw.json
at Object.onClose (file:///app/dist/call-pduzpefz.js:439:10)
at WebSocket.<anonymous> (file:///app/dist/client-hc4zXmLk.js:1538:23)
at WebSocket.emit (node:events:519:28)
at WebSocket.emitClose (/app/node_modules/.pnpm/ws@8.19.0/node_modules/ws/lib/websocket.js:273:10)
at Socket.socketOnClose (/app/node_modules/.pnpm/ws@8.19.0/node_modules/ws/lib/websocket.js:1346:15)
at Socket.emit (node:events:519:28)
at TCP.<anonymous> (node:net:346:12)
That error is a bit misleading: in the gateway handshake, if your shared-secret auth fails, the server will also try treating the provided --token as a device token. When that fails too, you end up with:
unauthorized: device token mismatch
In practice this almost always means: you’re not using the same gateway token the gateway is currently configured to expect (common if you ran onboarding and it wrote gateway.auth.token into openclaw.json, which overrides OPENCLAW_GATEWAY_TOKEN from .env).
Fix: run devices using the token the gateway is actually using (without printing it)
Run this (it pulls gateway.auth.token if set; otherwise falls back to OPENCLAW_GATEWAY_TOKEN):
sudo -u openclaw podman exec -it openclaw bash -lc '
TOK="$(node dist/index.js config get gateway.auth.token 2>/dev/null || true)";
if [[ -z "$TOK" || "$TOK" == "undefined" ]]; then TOK="$OPENCLAW_GATEWAY_TOKEN"; fi;
node dist/index.js devices list --url ws://127.0.0.1:18789 --token "$TOK"
'
You should now see a pending request from the Control UI browser. Then approve it (same token logic):
sudo -u openclaw podman exec -it openclaw bash -lc '
TOK="$(node dist/index.js config get gateway.auth.token 2>/dev/null || true)";
if [[ -z "$TOK" || "$TOK" == "undefined" ]]; then TOK="$OPENCLAW_GATEWAY_TOKEN"; fi;
node dist/index.js devices approve <requestId> --url ws://127.0.0.1:18789 --token "$TOK"
'
Refresh the dashboard tab and it should connect.
If you want an extra sanity check (safe)
This prints the dashboard URL without opening a browser (don’t paste the URL here if it includes a token):
sudo -u openclaw podman exec -it openclaw bash -lc 'node dist/index.js dashboard --no-open'
If the devices list command above still fails, paste only the output of (no secrets):
sudo -u openclaw podman exec -it openclaw bash -lc 'node dist/index.js config get gateway.auth.mode'
@balmy verge it worked, how do i check openclaw security audit --deep
For the Podman setup, run the security audit inside the running gateway container (so it uses the same config/state as the gateway):
sudo -u openclaw podman exec -it openclaw bash -lc \
'node dist/index.js security audit --deep'
Optional useful variants:
# machine-readable
sudo -u openclaw podman exec -it openclaw bash -lc \
'node dist/index.js security audit --deep --json'
# apply OpenClaw-only safe defaults (does NOT change host firewall/ssh)
sudo -u openclaw podman exec -it openclaw bash -lc \
'node dist/index.js security audit --fix'
If you paste output here, redact any tokens/hostnames/IPs.
@balmy verge is there any way to shorten the commands to the guide recommendeds like sudo -u openclaw podman exec -it openclaw bash -lc
'node dist/index.js security audit --deep --json' to become openclaw security audit --deep --json and etc?
Yes — two easy ways.
1) Shorten the podman exec (drop bash -lc)
Try this form (usually works, and is a lot cleaner):
sudo -u openclaw podman exec -it openclaw node /app/dist/index.js security audit --deep --json
(Using /app/dist/index.js avoids any “wrong working dir” weirdness.)
2) Make a tiny alias/function (recommended)
Add this to your shell rc (~/.bashrc or ~/.zshrc):
oc() { sudo -u openclaw podman exec -it openclaw node /app/dist/index.js "$@"; }
Then you can run:
oc security audit --deep --json
oc devices list --url ws://127.0.0.1:18789 --token "$TOK"
If you really want to type openclaw … exactly, you can also alias openclaw to that podman exec line — but I usually don’t recommend shadowing the real openclaw binary on your host. A separate oc/openclaw-podman wrapper is safer.