Skip to content

fix(browser): name Chrome 136+ IPv6 CDP binding in WSL2 portproxy hint#93481

Closed
ZengWen-DT wants to merge 1 commit into
openclaw:mainfrom
ZengWen-DT:fix/cdp-ipv6-binding-diagnostic
Closed

fix(browser): name Chrome 136+ IPv6 CDP binding in WSL2 portproxy hint#93481
ZengWen-DT wants to merge 1 commit into
openclaw:mainfrom
ZengWen-DT:fix/cdp-ipv6-binding-diagnostic

Conversation

@ZengWen-DT

Copy link
Copy Markdown
Contributor

Summary

In WSL2-to-Windows setups, when a CDP probe gets an empty reply through a netsh portproxy, OpenClaw's diagnostic asserted a single cause — a stale 127.0.0.1:9222 -> 127.0.0.1:9222 self-loop owned by svchost/iphlpsvc. As of Chrome 136+, a second cause produces the identical empty reply: Chrome ignores --remote-debugging-address and binds the CDP listener to [::1]:9222 (IPv6 loopback) only, so a v4tov4 portproxy forwarding to 127.0.0.1:9222 reaches nothing. Users following the old hint went looking for a self-loop that wasn't there, while the real fix is a v4tov6 portproxy.

This PR makes the empty-reply hint name both causes and tell the user to run netstat -ano | findstr :9222 to disambiguate, and documents the IPv6-binding case + v4tov6 remedy in the dedicated WSL2 remote-CDP troubleshooting guide.

Why guidance, not an auto-probe

Issue suggestion (2) proposed having OpenClaw probe both 127.0.0.1:9222 and [::1]:9222. In the reported topology the gateway runs in WSL2 and Chrome runs on Windows behind the portproxy, so [::1] from WSL2 is WSL2's own loopback, not Windows Chrome — OpenClaw cannot reach the Windows IPv6 listener to auto-detect this. The actionable improvement OpenClaw can make from the WSL2 side is to stop pointing users at the wrong cause and surface the correct remedy. Suggestion (1), the doc update, is implemented.

Changed surface

  • extensions/browser/src/browser/chrome.diagnostics.tsformatChromeCdpDiagnostic empty-reply hint now names both causes (self-loop and Chrome 136+ IPv6 binding) and the v4tov6 fix. Extracted to a commented WSL_EMPTY_REPLY_PORTPROXY_HINT constant.
  • docs/tools/browser-wsl2-windows-remote-cdp-troubleshooting.md — new "Chrome 136+ binds CDP to IPv6 loopback" section under Layer 1 + a clue in "Common misleading errors".

This is additive diagnostic text + docs. The CDP connection path itself is unchanged.

Verification

Real environment tested: Linux/WSL2; reproduced the field report's IPv4-vs-IPv6 split and the empty-reply diagnostic with real loopback servers (no Windows Chrome required to drive the diagnostic path under test).

Reproduction of the field-report signature — a server bound to [::1] only (mirroring Chrome 136+) answers on IPv6 but not IPv4, exactly as reported (curl.exe http://[::1]:9222 200 vs 127.0.0.1:9222 empty/refused):

Chrome (IPv6-only) listening on [::1]:35865
[::1]: HTTP 200
127.0.0.1: FAIL ECONNREFUSED
portproxy empty-reply fetch error message: other side closed

Diagnostic behavior, before → after — a TCP server that accepts then closes the socket reproduces the portproxy empty-reply. diagnoseChromeCdp("http://127.0.0.1:<port>") returns http_unreachable ("other side closed"), and formatChromeCdpDiagnostic is asserted in a live end-to-end test:

  • Before the fix (hint reverted), the real probe emits only the self-loop cause and the new assertions fail:
    AssertionError: expected 'CDP diagnostic: http_unreachable ... ' to contain 'v4tov6'
    Received: "... stale netsh portproxy self-loop where svchost/iphlpsvc owns the CDP port ... 127.0.0.1:9222 -> 127.0.0.1:9222 portproxy rule."
    
  • After the fix, the hint names the IPv6 binding cause and v4tov6 remedy. Existing self-loop substrings preserved.

Exact commands run after this patch:

pnpm test extensions/browser/src/browser/chrome.test.ts   # 51 passed (incl. new live empty-reply test)
pnpm tsgo:extensions                                       # clean
npx oxfmt --check --threads=1 <changed .ts files>          # clean
node scripts/format-docs.mjs --check <changed doc>         # clean

What was not tested: I could not exercise the genuine Chrome 136+ Windows binding (no Windows host with Chrome 136+ in this environment); the IPv6-only listener is simulated with a real [::1]-bound server that produces the same observable IPv4/IPv6 split and empty-reply diagnostic. pnpm docs:check-links:anchors could not run locally (missing @mintlify/scraping transitive dep + network); the new same-page anchor #chrome-136-binds-cdp-to-ipv6-loopback was verified by hand against the heading slug.

AI-assisted; all proof above was produced by real local runs.

Closes #54669

The empty-reply CDP diagnostic asserted only one cause (a stale netsh
self-loop), so when Chrome 136+ binds remote debugging to [::1] (IPv6)
only and a v4tov4 portproxy targets 127.0.0.1, the hint pointed users at
the wrong fix. Name both empty-reply causes and document the v4tov6
remedy in the WSL2 + Windows remote CDP troubleshooting guide.

Closes openclaw#54669

Co-Authored-By: Claude Opus 4.8 <[email protected]>
@openclaw-barnacle openclaw-barnacle Bot added triage: needs-real-behavior-proof Candidate: external PR needs after-fix proof from a real setup. docs Improvements or additions to documentation size: XS labels Jun 16, 2026
@vincentkoc vincentkoc self-assigned this Jun 16, 2026
@vincentkoc

Copy link
Copy Markdown
Member

Closing this because the proposed Chrome 136+ invariant is not supported by Chromium's implementation.

Current Chromium remote-debugging source binds 127.0.0.1 first and only falls back to ::1 when the IPv4 bind fails: https://chromium.googlesource.com/chromium/src/+/HEAD/content/browser/devtools/remote_debugging_server.cc

A v4tov6 portproxy rule may help a specific WSL2 host, but the PR describes it as a universal Chrome 136+ behavior and its tests only simulate a socket-close condition. The linked issue can remain open for a correctly scoped diagnostic/fix backed by a real affected setup.

@vincentkoc vincentkoc closed this Jun 16, 2026
steipete added a commit that referenced this pull request Jul 6, 2026
Base the repair on #93481 while matching Chromium's IPv4-first, IPv6-fallback listener contract and keeping CDP exposure loopback-scoped.

Co-authored-by: ZengWen-DT <[email protected]>
steipete added a commit that referenced this pull request Jul 6, 2026
Base the repair on #93481 while matching Chromium's IPv4-first, IPv6-fallback listener contract and keeping CDP exposure loopback-scoped.

Co-authored-by: ZengWen-DT <[email protected]>
steipete added a commit that referenced this pull request Jul 6, 2026
* fix(browser): diagnose Windows CDP listener mismatch

Base the repair on #93481 while matching Chromium's IPv4-first, IPv6-fallback listener contract and keeping CDP exposure loopback-scoped.

Co-authored-by: ZengWen-DT <[email protected]>

* style(docs): format browser troubleshooting table

* docs: refresh browser troubleshooting map

* fix(browser): diagnose reset CDP replies

* docs: refresh browser troubleshooting map

---------

Co-authored-by: ZengWen-DT <[email protected]>
@steipete

steipete commented Jul 6, 2026

Copy link
Copy Markdown
Contributor

Thank you, @ZengWen-DT. I took this PR as the implementation base, preserved your listener-family diagnosis and contributor credit, and landed the corrected version in #100590.

The landed fix keeps the useful v4tov6 recovery but scopes it to hosts where Windows proves Chrome is listening on [::1]; current Chromium source still prefers 127.0.0.1 and falls back to IPv6 only after the IPv4 bind fails. It also covers connection-reset replies, Chrome 136+'s actual non-default-profile requirement, and the CDP exposure boundary.

Proof included native Windows Chromium listener/proxy transitions, a real Dev Gateway + OpenAI agent controlling that Windows browser, 57/57 focused Browser tests, changed-surface type/lint/guard checks, and exact-head CI. Landed commit: 2830b3ef38786ee5799778ec7bfbab77dbf445bc.

github-actions Bot pushed a commit to Desicool/openclaw that referenced this pull request Jul 6, 2026
* fix(browser): diagnose Windows CDP listener mismatch

Base the repair on openclaw#93481 while matching Chromium's IPv4-first, IPv6-fallback listener contract and keeping CDP exposure loopback-scoped.

Co-authored-by: ZengWen-DT <[email protected]>

* style(docs): format browser troubleshooting table

* docs: refresh browser troubleshooting map

* fix(browser): diagnose reset CDP replies

* docs: refresh browser troubleshooting map

---------

Co-authored-by: ZengWen-DT <[email protected]>
giodl73-repo pushed a commit to giodl73-repo/openclaw that referenced this pull request Jul 8, 2026
* fix(browser): diagnose Windows CDP listener mismatch

Base the repair on openclaw#93481 while matching Chromium's IPv4-first, IPv6-fallback listener contract and keeping CDP exposure loopback-scoped.

Co-authored-by: ZengWen-DT <[email protected]>

* style(docs): format browser troubleshooting table

* docs: refresh browser troubleshooting map

* fix(browser): diagnose reset CDP replies

* docs: refresh browser troubleshooting map

---------

Co-authored-by: ZengWen-DT <[email protected]>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

docs Improvements or additions to documentation size: XS triage: needs-real-behavior-proof Candidate: external PR needs after-fix proof from a real setup.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Field Report] Chrome 136+ binds CDP to [::1] (IPv6) on Windows — portproxy v4tov4 breaks silently

3 participants