#6846: fix: bridge node.pair.* tools to device pairing store
gateway
Cluster:
Device Pairing and Gateway Fixes
## Problem
When a node connects via WebSocket for the first time, the gateway's connect handler creates a pending pairing request in the **device store** (`~/.openclaw/devices/pending.json`). However, the `node.pair.list`, `node.pair.approve`, and `node.pair.reject` handlers only check the **node store** (`~/.openclaw/nodes/`).
This means:
- `nodes pending` (agent tool) returns an empty list even when there are pending node pairing requests
- `nodes approve` fails with `unknown requestId` because it can't find the request
The only workaround is manually editing `devices/paired.json` and restarting the gateway — inaccessible for non-technical users.
## Root Cause
Two independent pairing systems (`device-pairing.ts` and `node-pairing.ts`) that don't communicate. The WS connect handler uses the device store for crypto-based verification, but the `node.pair.*` API handlers use the node store.
## Fix
Bridge the gap in the `node.pair.*` handlers:
1. **`node.pair.list`**: Also returns device-level pending requests that have a node role, merged with node-level pending requests (deduplicated by nodeId)
2. **`node.pair.approve`**: Falls back to `approveDevicePairing()` when the requestId isn't found in the node store
3. **`node.pair.reject`**: Same fallback pattern
This is a minimal, targeted fix — one file changed, no new dependencies.
## Testing
- TypeScript compiles clean (`tsc --noEmit` passes)
- Verified the fix resolves the exact scenario from #6836:
1. New node connects from LAN → rejected with "pairing required"
2. `node.pair.list` now returns the pending request from the device store
3. `node.pair.approve` with that requestId approves it in the device store
4. Node reconnects → paired successfully
Fixes #6836
<!-- greptile_comment -->
<h2>Greptile Overview</h2>
<h3>Greptile Summary</h3>
This PR updates `src/gateway/server-methods/nodes.ts` to bridge `node.pair.*` handlers with the device pairing store used by the WS connect flow.
- `node.pair.list` now merges node-store pending requests with device-store pending requests that have a node role, deduping by nodeId and sorting by timestamp.
- `node.pair.approve`/`node.pair.reject` now try node-store resolution first and fall back to `approveDevicePairing`/`rejectDevicePairing` when the requestId only exists in the device store.
Overall this aligns the CLI/API node pairing tools with how pairing requests are actually created when an unknown node connects via WebSocket, fixing the “empty pending list / unknown requestId” mismatch.
<h3>Confidence Score: 4/5</h3>
- This PR is likely safe to merge and should fix the reported pairing mismatch with low behavioral risk.
- The change is localized to one server-methods file and follows existing device-pairing patterns. Main risk is around edge cases/UX consistency (e.g., stale device pending entries and event consumers expecting `node.pair.resolved` even on device-store fallbacks), not core correctness.
- src/gateway/server-methods/nodes.ts
<!-- greptile_other_comments_section -->
**Context used:**
- Context from `dashboard` - CLAUDE.md ([source](https://app.greptile.com/review/custom-context?memory=fd949e91-5c3a-4ab5-90a1-cbe184fd6ce8))
- Context from `dashboard` - AGENTS.md ([source](https://app.greptile.com/review/custom-context?memory=0d0c8278-ef8e-4d6c-ab21-f5527e322f13))
<!-- /greptile_comment -->
Most Similar PRs
#17425: fix(gateway): auto-approve scope/role upgrades for already-paired d...
by sauerdaniel · 2026-02-15
84.7%
#22712: fix(gateway): auto-approve all device pairing for localhost connect...
by NewdlDewdl · 2026-02-21
84.3%
#21148: fix(gateway): add request-aware pairing recovery hints and docs
by cluster2600 · 2026-02-19
83.3%
#23503: fix: preserve pairing state on device token mismatch + migrate lega...
by dorukardahan · 2026-02-22
83.0%
#22262: fix(gateway): add pairing-repair command hint on 1008 connect failures
by karimnaguib · 2026-02-20
82.6%
#3744: Gateway: fix device pairing when local connection retries with exis...
by photon3710 · 2026-01-29
82.1%
#16310: fix(ws-connection): skip device pairing when client authenticates w...
by nawinsharma · 2026-02-14
81.2%
#19088: fix(gateway): allow startup with unset mode and fix pairing for local…
by mdanassaif · 2026-02-17
80.6%
#23690: fix(gateway): subagent sessions fail with pairing required on loopb...
by yinghaosang · 2026-02-22
80.3%
#22280: fix(gateway): silently auto-approve local paired-device scope upgrades
by abhishekp76 · 2026-02-21
80.3%