TL;DR

  • It almost never means OpenClaw is broken. The gateway is running fine. Your client (the CLI, the dashboard, a node, a chat channel) just hasn't been authorized to talk to it yet. The connection closes with WebSocket code 1008 and the message pairing required.
  • The fast fix, when the reason is `not-paired`: list the pending request and approve it.
openclaw devices list
openclaw devices approve <requestId>
  • If approval doesn't help, read the `reason`. OpenClaw tells you which of four cases you're in: not-paired, scope-upgrade, role-upgrade, metadata-upgrade. Each has a different fix, and "approve the device again" only solves the first one.
  • Watch for the lookalike. A token mismatch (AUTH_TOKEN_MISMATCH) fails in a similar-looking way but is a completely separate problem, and the pairing commands won't touch it. Telling the two apart is half the battle.

I'm not writing this as OpenClaw's documentation. I run OpenClaw and Hermes in production, and "pairing required" is one of the errors I've hit the most and misdiagnosed the most. Almost everything below is something I got wrong before I got it right. The goal is to help you find which of these you're looking at in about two minutes, instead of regenerating tokens at random until something works.

What "pairing required" actually means

When a client connects to the gateway, it presents a device identity: a key the gateway has to have approved ahead of time. If that key isn't on the approved list, the gateway refuses the connection, closes the socket with code 1008, and sends back a message that starts with pairing required. Your CLI wraps that into the line you see:

gateway connect failed: pairing required

Read that literally, because it's telling you the truth. connect failed is the client saying "I couldn't get in." pairing required is the server saying "I don't recognize this device." Neither one says the gateway is down, your config is corrupt, or your token is wrong. The gateway answered. It just answered "no."

The useful part is the reason the gateway attaches. There are four, and they are not interchangeable:

  • `not-paired`: this device has never been approved. First time on this machine, or the identity got reset.
  • `scope-upgrade`: the device is approved, but it's asking for permissions beyond what it was granted.
  • `role-upgrade`: approved, but asking to act in a higher role than it was given.
  • `metadata-upgrade`: approved, but requesting a change to its registered metadata.

Three of those four mean the device is already known. That's the detail almost every guide skips, and it's the one that saves you the most time: if your reason is scope-upgrade, approving the device a second time does nothing, because the device isn't the problem. Its permissions are.

The fast fix: approve the pending device

Start here, because it's the common case and it's easy. When an unrecognized device tries to connect, the gateway doesn't just reject it. It files a pending pairing request and waits for an operator to approve it. You are the operator.

openclaw devices list

That shows the pending requests, each with a request ID. Find yours (if you just triggered the error, it's the fresh one) and approve it:

openclaw devices approve <requestId>

Then reconnect. The client that got refused will now be handed a device token, store it, and reconnect authenticated. On chat channels there's an equivalent: an operator with pairing permission can approve the device request from chat, and the Telegram integration surfaces the pending request for approval in its own flow.

Two things trip people up here. First, the request ID is not the device ID. They're different values, and copying the wrong one gets you unknown requestId. Second, on a fresh machine the pending request only exists if the client reached the gateway and announced itself. If it never created a request (more on why that happens with remote gateways below), there's nothing for you to approve, and you'll approve into a void wondering why nothing changes.

One more fork worth knowing before you go deeper. This article is about a client being refused: a CLI, a dashboard, a node. If instead a chat sender is being refused (you messaged the bot on Telegram and it won't answer), that's a different system, channel pairing rather than device pairing, with its own commands. Approve that one with openclaw pairing list --channel telegram then openclaw pairing approve telegram <code>, not devices approve.

When approval isn't enough: scope and role

This is the one that cost me the most time, because the symptom lies. Everything says the device is paired. It connects. And then a specific operation fails with pairing required anyway, reason: scope-upgrade.

Here's the shape of it. A device gets approved once, early, for a narrow set of permissions: read-only, say, because the first thing it did was read some status. Later, something asks it to do more: run a scheduled job, write a config change, act with admin rights. The gateway looks at the request, sees the device is asking for scopes beyond what it holds, and instead of quietly escalating (which would be a security hole), it responds with a scope-upgrade request that has to be approved. Until someone approves it, the operation just fails, and it fails with a "pairing required" family error even though the device is sitting right there, paired.

I burned an evening on this. A backend identity had been pinned to a read-only scope on its first call, and every later admin action (a scheduled task, a config write) came back as "scope upgrade pending approval" instead of running. I kept re-approving the device, which was already approved, because I hadn't read the reason. The device was never the problem. The scope was.

The fix is to approve the elevated scope, not to re-pair from scratch. Look at what the failing operation needs: a paired device token can only manage its own device unless the caller also holds admin scope. If your automation needs to do more than that, the device has to be granted more than that, deliberately, and then the upgrade approved. Re-pairing gives you a fresh device with the same narrow scope and the same failure.

The lookalike: a token mismatch is not a pairing problem

Now the trap. There's a second failure that looks a lot like this one and is fixed the opposite way, and if you don't separate them you'll waste hours applying pairing fixes to a token problem, or the reverse.

Pairing is about which device is allowed to connect. The gateway also has a plain shared auth token, and that's a separate gate. If the token the client presents doesn't match the one the gateway expects, you get AUTH_TOKEN_MISMATCH, not PAIRING_REQUIRED. Same vague "it won't connect" feeling, different cause, and openclaw devices approve does nothing for it, because pairing isn't what failed: there's no pending request to approve. The device might be perfectly paired. The token is what's wrong.

Where it gets sneaky is where the token is read from. The gateway service reads it config-first, from gateway.auth.token in ~/.openclaw/openclaw.json. A local CLI client reads it env-first, from OPENCLAW_GATEWAY_TOKEN. On the same machine, those two can drift apart. You set the environment variable, you're sure the token is "set," and the running gateway is comparing against a different value in the config file. Everything says a token exists. They just aren't the same token.

I've written up the where-does-the-token-live side of this in more detail in the OpenClaw security checklist; the point here is narrower and diagnostic. Before you touch pairing at all, check the error code. If it says token mismatch, or you're seeing a 401 with a missing or invalid bearer token, stop. That's not pairing, and no amount of devices approve will fix it. Confirm which source your gateway actually reads the token from, and make the two agree. If you see a secretref-env:NAME or $VAR string where the token should be, that's a reference to an environment variable, not the token itself; if the variable isn't set, you effectively have no token.

Why it's almost always the remote gateway

If "pairing required" shows up the moment you point a client at a gateway over Tailscale, a VPN, or a different host, that's not a coincidence, and understanding why fixes a whole category of confusion.

OpenClaw treats a client on the same machine as the gateway differently from a client coming in over the network. A local client, on loopback or a trusted address, can be allowed to pair itself silently: the gateway trusts its own host. By default, a remote client can't do that. It has to be explicitly approved, once per device identity, by design (an operator can opt into auto-approving specific trusted remote networks, but that's a deliberate choice, not the default). So the same setup that "just worked" locally starts demanding approval the moment you move the client to another box. Nothing broke. You crossed the line where silent local pairing stops applying.

There's a second remote-only trap. When you connect to a remote gateway, the CLI sometimes fails to generate a device identity on its own, which means it never files a pending request, and if there's no pending request, there's nothing for you to approve. You sit there running openclaw devices approve against an empty list. The fix is to give the client an explicit identity so it creates a proper request. For a node, that's openclaw node run with --node-id and --display-name; then approve the request that shows up.

And know your mode. OpenClaw has a gateway.mode setting with two values, local and remote. local means the CLI can start and talk to a gateway on this machine; remote means it targets a gateway somewhere else and won't start one locally. I once wrote remote into the config on a single-host box by mistake, and the local gateway refused to start. Mode remote disables that. If you're all on one machine, you want local. If you're pointing at another host, remote with the right gateway.remote.url. Getting this backward produces connection failures that have nothing to do with pairing and everything to do with the client looking for the gateway in the wrong place.

"Connect failed" right after a restart or update

One more source of false alarms, and it's a timing problem, not an auth problem. Right after the gateway restarts (including the restart that an update or a config change triggers on its own), there's a window where clients get "connect failed." It's not always pairing. Sometimes the gateway just isn't ready yet.

A gateway can take a real number of seconds to come up. I've watched a production one take around eighteen. A client that tries to connect during that window, or a bootstrap step that fires a command into a gateway that's mid-restart, gets a failure that looks alarming and means nothing: wait, retry, it's fine. I've had update jobs report failure for this reason (a command timed out because it collided with the restart the config change itself had triggered) when the new version was installed and healthy the whole time.

The distinction worth internalizing: some connect failures are worth retrying and some aren't. A cold start or a transient protocol hiccup is retryable: give it a few seconds and it clears. An auth, device, or scope failure is not; retrying pairing required in a loop will never approve your device, and I've seen a client sit "offline" forever after an upgrade because it treated a version mismatch as permanent and never re-checked. So: if the failure appeared the instant a restart or update happened, wait for the gateway to report healthy and try again before you touch anything. If it persists after the gateway is up, then read the reason and treat it as real.

"Set" is not "applied"

Short, but it catches people. You change the auth config or rotate the token, the file writes correctly, and the running gateway keeps enforcing the old value. Written is not the same as in effect. A live gateway holds its own view of the config, and a bare write doesn't always reach it; the change lands when the gateway reloads or restarts and rebuilds its state from the file.

I hit the config-doesn't-apply problem from the other direction once too, through a dead config watcher, which I wrote about in the security checklist. Same lesson, different trigger: after you change anything auth-related, confirm it against the live gateway, not against the fact that the file saved. Otherwise you'll "fix" a token, see the file update, and stare at the same failure because the gateway never picked it up.

A quick way to tell them apart

When you see a connection failure, don't guess. Read the error, and walk it:

  • `pairing required`, reason `not-paired` → the device is unknown. openclaw devices list, then openclaw devices approve <requestId>. Reconnect.
  • `pairing required`, reason `scope-upgrade` / `role-upgrade` → the device is known but under-privileged. Approve the upgrade, or grant the scope the operation needs. Don't re-pair.
  • `AUTH_TOKEN_MISMATCH`, or a `401` on the bearer token → not pairing. Fix the token, and check whether your gateway reads it config-first or env-first.
  • Connect failed the instant a restart or update happened → probably a cold start. Wait for healthy, retry, then re-read.
  • `gateway.mode` mismatch → local client with remote set (or the reverse). Fix the mode before anything else.

Most of the time, thirty seconds with the actual error text beats an hour of trying fixes at random. openclaw doctor and openclaw doctor --fix are worth running too (the doctor catches several of the config and token-source mistakes above automatically), but run it after you've read the reason, so you know whether it addressed your actual case or a different one.

What this can't tell you

I'll be straight about the edges. This covers the failures I've hit, which is not all of them. If you've read the reason, it's genuinely not-paired, you've approved the request, your mode is right, the token matches, the gateway is up and healthy, and it still won't connect, then you're past the common causes and into something more specific: a version incompatibility between client and gateway, a broken WebSocket transport, a reverse proxy in front of the gateway mangling the handshake (proxies that gate on a ?token= query parameter break it, because the real token rides inside the handshake after the socket opens, not in the URL), a port conflict, or an actual bug. At that point the pending-request list and the reason code have told you what they can, and the next stop is the gateway logs and, if it reproduces, an upstream issue.

None of this is a security review, either. Getting a client to connect is not the same as configuring the gateway safely. For that, the exposure and auth items in the security checklist matter more than any pairing fix.

If you'd rather not chase this every release

All of the above is manageable once you've seen it a few times. What wears on you is that it comes back: OpenClaw ships updates, the token wiring or the pairing state can shift underneath one, and every upgrade is another chance to spend an evening on a 1008. That's the part I do so I don't have to think about it, and it's most of what Cain is. The part that's relevant here: a new version is validated against an upgrade matrix before it's allowed to roll out, so a pairing or token regression is the kind of thing that gets caught before it reaches the server provisioned for you. The security fixes still reach you, without someone else's regression riding along. It runs OpenClaw and Hermes on that server, one client per server. That's one option, not the only right answer. If you're happy running it yourself, the steps above are the ones I'd follow.

FAQ

What does "openclaw gateway connect failed: pairing required" mean? The gateway is running, but your client's device identity hasn't been approved (or is approved but asking for more access than it was granted), so the connection is refused with WebSocket code 1008. It's an authorization step, not a crash. Read the reason, then approve the device or the upgrade and reconnect.

How do I approve a pairing request in OpenClaw? Run openclaw devices list to see the pending requests, then openclaw devices approve <requestId> with the ID of yours. On chat channels, an operator with pairing permission can approve the request from the channel itself. Reconnect afterward.

Why do I only get "pairing required" on a remote or Tailscale gateway? Because by default a remote client can't pair itself silently; only local clients on a trusted address can. A setup that worked locally will demand explicit approval the moment the client is on another host. For a node, give it an explicit identity (openclaw node run --node-id <id> --display-name <name>) so it files a request you can approve.

What's the difference between "pairing required" and a token mismatch? Pairing is about which device is allowed to connect; the token is a separate shared secret. pairing required (1008) is fixed by approving the device; AUTH_TOKEN_MISMATCH is fixed by making the client's token match the gateway's. The pairing commands do nothing for a token problem, and vice versa. Check the error code first.

Where does OpenClaw read its gateway auth token from? The gateway service reads it config-first, from gateway.auth.token in ~/.openclaw/openclaw.json, and falls back to the OPENCLAW_GATEWAY_TOKEN environment variable. A local CLI prefers the env variable. If those two disagree on the same machine, the gateway can reject a token you're sure is "set."

How do I fix "scope upgrade pending approval" (error 1008)? That reason means the device is already paired but is requesting permissions beyond what it holds. Approve the scope upgrade, or grant the device the scope the operation needs. Don't re-pair, which just gives you a fresh device with the same narrow permissions.

Does `openclaw doctor --fix` fix "pairing required"? It fixes several config and token-source problems that look like pairing failures, which is useful. It does not replace approving a genuinely unpaired device. For a not-paired reason, you still approve the request. Read the reason first, then let the doctor handle the config side.

How do I restart the OpenClaw gateway safely? Restart it with openclaw gateway restart, then wait for it to report healthy (openclaw gateway status) before you reconnect or run commands against it. A gateway mid-restart returns connection failures that clear on their own. If a config or token change prompted the restart, verify the change against the live gateway once it's up, not just against the saved file.

Ilya Prudnikov runs private OpenClaw and Hermes deployments. This is an operator's field notes on one specific error, not OpenClaw's official documentation; when in doubt, the project's own docs are the source of truth for exact commands.