fix: stop reconnecting on protocol mismatch#98414
Conversation
|
Codex review: needs changes before merge. Reviewed July 6, 2026, 2:01 AM ET / 06:01 UTC. Summary PR surface: Source -2, Tests +66, Docs +1. Total +65 across 5 files. Reproducibility: yes. Source inspection shows current main can schedule reconnects after a PROTOCOL_MISMATCH connect failure because stored details and the non-recoverable gate do not classify that terminal detail code; I did not execute tests in this read-only review. Review metrics: 1 noteworthy metric.
Root-cause cluster Members:
Proposal only: this assessment does not dispatch repair, suppress jobs, mutate sibling items, close, or merge anything. Merge readiness Overall follows the weaker of proof and patch quality, so missing proof can cap an otherwise strong patch. Rank-up moves:
Risk before merge
Maintainer options:
Next step before merge
Security Review findings
Review detailsBest possible solution: Land the Control UI runtime and test changes after dropping the direct CHANGELOG.md edit and keeping the release-note context in the PR body. Do we have a high-confidence way to reproduce the issue? Yes. Source inspection shows current main can schedule reconnects after a PROTOCOL_MISMATCH connect failure because stored details and the non-recoverable gate do not classify that terminal detail code; I did not execute tests in this read-only review. Is this the best way to solve the issue? Yes for the Control UI runtime path: normalizing details once in GatewayRequestError and feeding the existing reconnect gate is the narrow maintainable fix. The direct CHANGELOG.md edit is not part of the best solution and should be removed. Full review comments:
Overall correctness: patch is correct AGENTS.md: found and applied where relevant. Codex review notes: model internal, reasoning high; reviewed against f9bf5f589763. Label changesLabel changes:
Label justifications:
Evidence reviewedPR surface: Source -2, Tests +66, Docs +1. Total +65 across 5 files. View PR surface stats
Acceptance criteria:
What I checked:
Likely related people:
What the crustacean ranks mean
Shiny media proof means a screenshot, video, or linked artifact directly shows the changed behavior. Runtime, network, CSP, and security claims still need visible diagnostics. How this review workflow works
Review history (3 earlier review cycles)
|
b5fb210 to
cd9f687
Compare
cd9f687 to
bd769b4
Compare
bd769b4 to
8e74e56
Compare
8e74e56 to
bc7cefe
Compare
bc7cefe to
87f41b7
Compare
|
Maintainer refactor and exact-head verification are complete.
Ready to land through the repository-native prepare/merge guard. |
|
Merged via squash.
|
* origin/main: (1287 commits) fix(android): block loopback canvas navigation (openclaw#99874) fix(hooks): suppress unhandled stdout/stderr stream errors in gmail watcher (openclaw#100519) fix(memory-core): guard qmd mcporter JSON.parse against non-JSON stdout (openclaw#98381) fix(build): fall back to tsx for build TypeScript scripts (openclaw#91262) feat(skills): suggest saving detected reusable workflows by default (openclaw#95477) (openclaw#100692) docs(changelog): remove generated release-note entries feat(telegram): offer BotFather web app flow in setup help and docs (openclaw#100540) fix(ios): unify Talk and Settings row typography on one branded detail row (openclaw#100515) feat(gateway): add persisted crash-loop breaker and fatal-config exit contract refactor(macos): lock and unify PortGuardian tunnel record persistence so concurrent app instances cannot lose orphan records (openclaw#100601) fix: stop reconnecting on protocol mismatch (openclaw#98414) fix(maint): reuse recent hosted gates after rebase (openclaw#100663) fix(ui): reopen web terminals without stale content (openclaw#100665) fix(browser): diagnose empty WSL2 Chrome replies (openclaw#100590) fix(ios): chat snaps back to bottom when scrolling to top via status-bar tap (openclaw#100502) Treat already-compacted CLI compaction as no-op (openclaw#99136) docs(changelog): remove direct main fix entry fix(feishu): strip internal tool-trace banners from outbound text (openclaw#98705) fix(message): thread --limit through to CLI formatter and surface provider pagination hints (openclaw#99089) fix(voyage): close response body stream when batch output JSONL parsing throws (openclaw#98840) ... # Conflicts: # extensions/memory-wiki/package.json
* fix: stop reconnecting on protocol mismatch * fix(ui): stop protocol mismatch reconnects * test(ui): assert protocol mismatch recovery copy * test(ui): count gateway reconnect attempts * test(gateway): keep detail-less reconnect case typed * test(gateway): keep pairing retry fixture typed --------- Co-authored-by: haruaiclone-droid <[email protected]> Co-authored-by: Peter Steinberger <[email protected]>
* fix: stop reconnecting on protocol mismatch * fix(ui): stop protocol mismatch reconnects * test(ui): assert protocol mismatch recovery copy * test(ui): count gateway reconnect attempts * test(gateway): keep detail-less reconnect case typed * test(gateway): keep pairing retry fixture typed --------- Co-authored-by: haruaiclone-droid <[email protected]> Co-authored-by: Peter Steinberger <[email protected]>
Closes #98413.
What Problem This Solves
When the Control UI and Gateway disagree on the connection protocol, the Gateway returns
PROTOCOL_MISMATCH. The browser surfaced the failure but treated it like a retryable disconnect, opening another WebSocket every retry interval and repeating a connection that cannot succeed.Why This Change Was Made
The fix keeps normalized protocol-mismatch details on
GatewayRequestErrorand classifies that structured error as a non-recoverable connect failure. This extends the existing authentication/pairing reconnect gate instead of adding a second retry policy. Ordinary transient closes and explicitly retryable pairing flows keep their existing reconnect behavior.User Impact
Users now get the existing actionable protocol guidance once, without a reconnect loop. Updating the mismatched client or Gateway remains the supported recovery path.
Evidence
PROTOCOL_MISMATCH, verifies the rendered guidance, waits beyond the retry window, and asserts that only one Gatewayconnectrequest was sent.run_04a548fbf6ecpassedpnpm tsgo:test:src, all 42 reconnect-gating assertions, all 38 Gateway unit assertions, and all 4login-gate.e2e.test.tsreal-Chromium scenarios on87f41b7c1a06fb8bf6cef8428a2baea8c82b0956.connectrequest; unrelated Vite HMR sockets are deliberately excluded from that assertion.