#Gateway stuck in device-pair loop after 2026.3.13 β†’ 2026.4.21 upgrade, can't approve through CLI or

1 messages Β· Page 1 of 1 (latest)

trim lichen
#

2026.4.21 gateway stuck in device-pair loop after host migration
Env: 2026.4.21 on macOS (Apple Silicon), upgraded from 2026.3.13 today. Local loopback, token auth, 10 Telegram bots, Ollama+GLM.
Symptom: Gateway reaches Capability: pairing-pending and stays. Infinite device.pair.requested loop for one device, new requestId every 20-100ms, isRepair: true, scopes operator.approvals + operator.read.
Suspected cause: Device is paired platform: linux from when OpenClaw ran on a GCP VPS. After migrating to this Mac, every boot tries to repair the platform pin (claimedPlatform=darwin vs pinnedPlatform=linux). It's also the CLI's auth device (clientId: cli), so the CLI's own auth is what's pending β€” breaking every CLI-based approval path.

Tried:
devices approve <requestId> β€” always unknown requestId, rotates faster than command completes
Scripted list+approve in one pipeline β€” same
Stable requestId from pending.json β€” still fails, file rewrites on every connection
Full downgrade to 3.13 then re-upgrade β€” same on both
doctor --fix
Dashboard Manual RPC device.pair.approve β€” also unknown requestId, rotates within dashboard session
channels.logout for all 10 Telegram accounts β€” slowed briefly but didn't stop. Suggests pair requests come from gateway-client itself, not the Telegram plugin

State: Dashboard reachable + paired with full operator scope. Pending always has 1 entry for same deviceId, requestId rotates. Paired list still has the broken Linux device. Log shows device.pair.requested every few hundred ms, client=gateway-client. Snapshots exist, no data risk.
Not tried: device.token.revoke on the Linux device β€” reluctant without knowing if it stops the regeneration source or just records a revoke.
Q: Intended recovery for an operator device whose platform pin no longer matches the host after a legit migration? Any approval path not requiring CLI auth to already be valid? Is device.token.revoke the right move?
Logs/RPC output available on request.

trim lichen
#

Anyone that can help?

whole plinthBOT
#

Let me verify the docs/source locally so I don’t make up a recovery path.

#

Yeah, I think the right move here is remove the stale paired-device record, not device.token.revoke.

What you’re describing matches a repair loop on an already-paired device. The killer detail is that revoke only revokes the token, it does not clear the paired record or its pinned metadata, so the bad linux platform pin can keep retriggering repair. remove clears the paired record and pending entries for that device.

Best recovery path, since CLI auth is the broken device:

  1. In the already-paired Dashboard Manual RPC, call:

    • method: device.pair.remove
    • params:
      {"deviceId":"<the stale linux-pinned deviceId>"}
      
  2. Then reconnect / rerun openclaw devices list.

    • If a fresh pending request appears, approve that one.
    • On local loopback shared-secret paths, it may settle automatically.
#
  1. Do not start with device.token.revoke. I would only consider revoke later if you still have token drift after the stale pairing record is gone.

So, short answer to your questions:

  • Intended recovery after legit host migration? Remove the stale paired device, then re-pair.
  • Approval path that does not need CLI auth already working? Yes, Dashboard Manual RPC on an already-paired operator session.
  • Is device.token.revoke the right move? No, not first. device.pair.remove is the better move here.

Docs:

If you want, paste the deviceId row from devices list first and I’ll sanity check that you’re removing the right one.

trim lichen
#

Thanks β€” paired-device row from device.pair.list:
deviceId: 71e6a2fa176c3280396fbff8db03ecde771ed33160d1616d9eb9b79a2d289bbc
platform: linux
clientId: cli
clientMode: cli
scopes: operator.admin, operator.approvals, operator.pairing, operator.read, operator.write
createdAtMs: 1769274748840
That's the original CLI pairing from when OpenClaw ran on the GCP VPS. The other 3 paired devices are MacIntel webchat dashboards (correct). Going to remove this one β€” does it look right?

whole plinthBOT
#

Yes, that looks like the right one.

The signals all line up:

  • clientId: cli
  • clientMode: cli
  • platform: linux
  • old VPS-era operator scopes
  • same device that keeps generating the repair request

So I’d remove that exact deviceId:

{"deviceId":"71e6a2fa176c3280396fbff8db03ecde771ed33160d1616d9eb9b79a2d289bbc"}

via device.pair.remove in Dashboard Manual RPC, or openclaw devices remove <deviceId> if you have a working session for it.