openclaw / openclaw/openclaw-windows-node
[Bug]: Operator RPC can be sent before connect/hello-ok, causing 1008 PolicyViolation
Nobody has claimed this yet.
- Dominant language
- C#
- Stars
- 2.1k
- Forks
- 295
- Avg merge
- 1d 6h
- Merged PRs (30d)
- 99
Description
Context
This issue was originally reported in:
openclaw/openclaw#148115
Core triage determined that the Gateway behavior is correct and that the defect belongs to the Windows Companion client maintained in this repository.
The original issue was closed as out-of-repository scope, not because the reported race was considered invalid.
Summary
During Windows Companion startup or reconnect, the operator WebSocket can send RPCs such as node.list, device.pair.list, or models.list before the required connect handshake completes.
The Gateway then correctly rejects the request and closes the socket with:
1008 PolicyViolation: invalid handshake: first request must be connect
Expected behavior
Application RPCs should only be sent after the operator WebSocket has completed the connect handshake and received hello-ok.
Known-good sequence:
operator socket opened
→ connect sent
→ hello-ok received
→ Handshake complete
→ models.list / node.list / other RPCs
Actual behavior
During reconnects, the operator WebSocket can be open before its protocol handshake is complete.
Another connection event may then trigger an RPC on the operator socket before connect has been sent.
Observed example:
04:09:23.717 operator: Connecting to gateway
04:09:23.871 node: Sending connect (role=node)
04:09:24.310 node: Received hello-ok
04:09:24.314 operator: gateway connected, waiting for challenge...
04:09:24.315 operator: Received connect.challenge
04:09:24.316 node: Node status changed: Connected
04:09:24.317 operator: node.list failed: invalid handshake: first request must be connect
04:09:24.318 operator: Server closed connection: PolicyViolation (1008)
04:09:24.321 operator: gateway reconnecting in 4548ms
04:09:26.953 operator: Sending connect
The node.list RPC was sent before the operator socket sent connect.
A startup variant was also observed:
03:16:03.489 operator: gateway connected, waiting for challenge...
03:16:03.520 [ChatBridge] proactive: requesting models.list and sessions.list
03:16:03.523 Sending frame: models.list
03:16:03.541 PolicyViolation - first request must be connect
03:16:05.625 Sending connect
Frequency
Historical Companion logs contained 29 occurrences of this 1008 PolicyViolation.
- 28 occurred during reconnect:
- 22 involved
node.list - 6 involved
device.pair.list
- 22 involved
- 1 startup occurrence involved
models.list
After an unrelated WSL lifecycle issue was fixed, a stable 5.5-minute capture showed:
- zero reconnects
- zero
PolicyViolationevents - zero
first request must be connect - zero connection failures
- stable operator/node sockets
Version
- Windows Companion:
2026.9.3 - Companion commit:
84928c43 - Gateway:
2026.9.2 - Gateway protocol:
4 - OS: Windows 11
Source-level evidence
The Companion currently exposes gateway readiness as:
IsConnectedToGateway => IsConnected
However, IsConnected appears to represent WebSocket-open state rather than protocol-handshake completion.
A separate handshake state already exists as _hasHandshakeSnapshot.
SendTrackedRequestAsync also appears to check socket connectivity without requiring hello-ok completion.
Observed request paths include:
RequestNodesAsyncRequestDevicePairListAsync- proactive
models.liststartup requests
This allows RPC admission during the window where the socket is open but the operator handshake has not completed yet.
Possible fix
Gateway readiness could require both socket connectivity and handshake completion, for example:
public bool IsConnectedToGateway =>
IsConnected && Volatile.Read(ref _hasHandshakeSnapshot);
It may also be useful to add a defensive handshake-readiness guard in tracked RPC send paths so application RPCs cannot be sent before hello-ok.
Gateway behavior
The Gateway appears to be behaving correctly.
It requires the first application frame to be connect, and rejects other requests with 1008 PolicyViolation.
The original core triage explicitly identified the Windows Companion as the correct repair location.
Impact
Severity: intermittent reconnect failure / degraded connection reliability.
No data loss was observed.
A failed operator connection is discarded and retried after approximately 4.5 seconds.
During reconnect activity, the Windows Companion may show user-facing states such as:
Authentication failedTransport errorGateway connection failed
Reproduction
A deterministic current-main reproduction has not yet been performed.
The evidence is based on:
- Windows Companion logs
- Gateway journal
- Windows process/socket inspection
- Companion source review
- repeated historical occurrences
Related issue
openclaw/openclaw#148115
Screenshots
Screenshots below show the user-visible connection/reconnect failure states.
Contributor guide
No contributing guide indexed for this repository
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start by tracing IsConnectedToGateway, _hasHandshakeSnapshot, and SendTrackedRequestAsync, then inspect RequestNodesAsync, RequestDevicePairListAsync, and the proactive models.list request path. Confirm how hello-ok updates handshake state and how reconnect events admit RPCs. Done means application RPCs cannot be sent until the operator connect handshake completes, with coverage for the startup or reconnect race if the existing test structure supports it.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- csharp
- Domain
- desktop, networking
- Issue type
- Bug
- Difficulty
- 3/5
- Estimated time
- 1-2 days
- Activity status
- Active
- Clarity
- Mostly clear
- Newbie friendliness
- 58/100