Some checks failed
ClawSweeper Dispatch / dispatch (push) Has been cancelled
CodeQL / Security High (actions) (push) Has been cancelled
CodeQL / Security High (channel-runtime-boundary) (push) Has been cancelled
CodeQL / Security High (core-auth-secrets) (push) Has been cancelled
CodeQL / Security High (mcp-process-tool-boundary) (push) Has been cancelled
CodeQL / Security High (network-ssrf-boundary) (push) Has been cancelled
CodeQL / Security High (plugin-trust-boundary) (push) Has been cancelled
CodeQL / Security High (process-exec-boundary) (push) Has been cancelled
Docs Sync Publish Repo / sync-publish-repo (push) Has been cancelled
Docs / docs (push) Has been cancelled
OpenClaw Stable Main Closeout / Resolve stable release closeout inputs (push) Has been cancelled
OpenClaw Stable Main Closeout / Verify stable main closeout (push) Has been cancelled
Workflow Sanity / no-tabs (push) Has been cancelled
Workflow Sanity / actionlint (push) Has been cancelled
Workflow Sanity / generated-doc-baselines (push) Has been cancelled
CI / runner-admission (push) Has been cancelled
CI / preflight (push) Has been cancelled
CI / security-fast (push) Has been cancelled
CI / pnpm-store-warmup (push) Has been cancelled
CI / build-artifacts (push) Has been cancelled
CI / native-i18n (push) Has been cancelled
CI / ${{ matrix.check_name }} (push) Has been cancelled
CI / ${{ matrix.checkName }} (push) Has been cancelled
CI / checks-node-compat-node22 (push) Has been cancelled
CI / check-bundled-channel-config-metadata (push) Has been cancelled
CI / check-dependencies (push) Has been cancelled
CI / check-guards (push) Has been cancelled
CI / check-lint (push) Has been cancelled
CI / check-prod-types (push) Has been cancelled
CI / check-shrinkwrap (push) Has been cancelled
CI / check-test-types (push) Has been cancelled
CI / check-additional-boundaries-a (push) Has been cancelled
CI / check-additional-boundaries-bcd (push) Has been cancelled
CI / check-additional-extension-bundled (push) Has been cancelled
CI / check-additional-extension-channels (push) Has been cancelled
CI / check-additional-extension-package-boundary (push) Has been cancelled
CI / check-additional-runtime-topology-architecture (push) Has been cancelled
CI / check-session-accessor-boundary (push) Has been cancelled
CI / check-session-transcript-reader-boundary (push) Has been cancelled
CI / check-docs (push) Has been cancelled
CI / skills-python (push) Has been cancelled
CI / macos-swift (push) Has been cancelled
CI / ios-build (push) Has been cancelled
CI / ci-timings-summary (push) Has been cancelled
Native App Locale Refresh / Refresh native fa (push) Has been cancelled
Native App Locale Refresh / Refresh native fr (push) Has been cancelled
Native App Locale Refresh / Refresh native hi (push) Has been cancelled
Native App Locale Refresh / Refresh native id (push) Has been cancelled
Native App Locale Refresh / Refresh native it (push) Has been cancelled
Native App Locale Refresh / Refresh native ja-JP (push) Has been cancelled
Control UI Locale Refresh / plan (push) Has been cancelled
Control UI Locale Refresh / Refresh ${{ matrix.locale }} (push) Has been cancelled
Control UI Locale Refresh / Commit control UI locale refresh (push) Has been cancelled
Live Media Runner Image / Build live media runner image (push) Has been cancelled
Native App Locale Refresh / Refresh native ar (push) Has been cancelled
Native App Locale Refresh / Refresh native de (push) Has been cancelled
Native App Locale Refresh / Refresh native es (push) Has been cancelled
Native App Locale Refresh / Refresh native ko (push) Has been cancelled
Native App Locale Refresh / Refresh native nl (push) Has been cancelled
Native App Locale Refresh / Refresh native pl (push) Has been cancelled
Native App Locale Refresh / Refresh native pt-BR (push) Has been cancelled
Native App Locale Refresh / Refresh native ru (push) Has been cancelled
Native App Locale Refresh / Refresh native sv (push) Has been cancelled
Native App Locale Refresh / Refresh native th (push) Has been cancelled
Native App Locale Refresh / Refresh native tr (push) Has been cancelled
Native App Locale Refresh / Refresh native uk (push) Has been cancelled
Native App Locale Refresh / Refresh native vi (push) Has been cancelled
Native App Locale Refresh / Refresh native zh-CN (push) Has been cancelled
Native App Locale Refresh / Refresh native zh-TW (push) Has been cancelled
Native App Locale Refresh / Commit native locale refresh (push) Has been cancelled
Plugin Init Scaffold Validation / Validate provider scaffold (push) Has been cancelled
Plugin NPM Release / preview_plugins_npm (push) Has been cancelled
Plugin NPM Release / Validate release publish approval (push) Has been cancelled
Plugin NPM Release / preview_plugin_pack (push) Has been cancelled
Plugin NPM Release / publish_plugins_npm (push) Has been cancelled
Sandbox Common Smoke / sandbox-common-smoke (push) Has been cancelled
Website Installer Sync / static (push) Has been cancelled
Website Installer Sync / linux-docker (push) Has been cancelled
Website Installer Sync / macos-installer (push) Has been cancelled
Website Installer Sync / windows-installer (push) Has been cancelled
Website Installer Sync / sync-website (push) Has been cancelled
Adolf is a fork/vendored clone of github.com/openclaw/openclaw (v2026.6.11), free to diverge. Tree copied sans upstream .git; upstream remote added for future syncs. Node pinned to 24 (.nvmrc); engines already require >=22.19. Preserves docs/ARCHITECTURE.md. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01LeqyaxJF2nbRXJtae2kNB2
184 lines
8.1 KiB
Markdown
184 lines
8.1 KiB
Markdown
---
|
|
summary: "Troubleshoot WSL2 Gateway + Windows Chrome remote CDP in layers"
|
|
read_when:
|
|
- Running OpenClaw Gateway in WSL2 while Chrome lives on Windows
|
|
- Seeing overlapping browser/control-ui errors across WSL2 and Windows
|
|
- Deciding between host-local Chrome MCP and raw remote CDP in split-host setups
|
|
title: "WSL2 + Windows + remote Chrome CDP troubleshooting"
|
|
---
|
|
|
|
In the common split-host setup, OpenClaw Gateway runs inside WSL2, Chrome runs
|
|
on Windows, and browser control must cross the WSL2/Windows boundary. Several
|
|
independent problems can surface at once (see
|
|
[issue #39369](https://github.com/openclaw/openclaw/issues/39369)): CDP
|
|
transport, Control UI origin security, and token/pairing can each fail on
|
|
their own while producing similar-looking errors. Work through the layers
|
|
below in order instead of guessing which one is broken.
|
|
|
|
## Choose the right browser mode first
|
|
|
|
### Option 1: raw remote CDP from WSL2 to Windows
|
|
|
|
Use a remote browser profile pointing from WSL2 to a Windows Chrome CDP
|
|
endpoint. Choose this when the Gateway stays inside WSL2, Chrome runs on
|
|
Windows, and browser control needs to cross the WSL2/Windows boundary.
|
|
|
|
### Option 2: host-local Chrome MCP
|
|
|
|
Use the `existing-session` driver (`user` profile) only when the Gateway runs
|
|
on the same host as Chrome, you want the local signed-in browser state, you do
|
|
not need cross-host browser transport, and you do not need `responsebody`,
|
|
PDF export, download interception, or batch actions (Chrome MCP profiles do
|
|
not support these).
|
|
|
|
For WSL2 Gateway + Windows Chrome, use raw remote CDP. Chrome MCP is
|
|
host-local, not a WSL2-to-Windows bridge.
|
|
|
|
## Working architecture
|
|
|
|
- WSL2 runs the Gateway on `127.0.0.1:18789`
|
|
- Windows opens the Control UI in a normal browser at `http://127.0.0.1:18789/`
|
|
- Windows Chrome exposes a CDP endpoint on port `9222`
|
|
- WSL2 can reach that Windows CDP endpoint
|
|
- OpenClaw points a browser profile at the address reachable from WSL2
|
|
|
|
## Critical rule for the Control UI
|
|
|
|
When the UI is opened from Windows, use Windows localhost unless you have a
|
|
deliberate HTTPS setup:
|
|
|
|
```text
|
|
http://127.0.0.1:18789/
|
|
```
|
|
|
|
Do not default to a LAN IP. Plain HTTP on a LAN or tailnet address can
|
|
trigger insecure-origin/device-auth behavior unrelated to CDP itself. See
|
|
[Control UI](/web/control-ui).
|
|
|
|
## Validate in layers
|
|
|
|
Work top to bottom; do not skip ahead. Fixing one layer can still leave a
|
|
different error visible from a layer further down.
|
|
|
|
### Layer 1: verify Chrome is serving CDP on Windows
|
|
|
|
```powershell
|
|
chrome.exe --remote-debugging-port=9222
|
|
```
|
|
|
|
From Windows, verify Chrome itself first:
|
|
|
|
```powershell
|
|
curl http://127.0.0.1:9222/json/version
|
|
curl http://127.0.0.1:9222/json/list
|
|
```
|
|
|
|
If this fails on Windows, OpenClaw is not the problem yet.
|
|
|
|
### Layer 2: verify WSL2 can reach that Windows endpoint
|
|
|
|
From WSL2, test the exact address you plan to use in `cdpUrl`:
|
|
|
|
```bash
|
|
curl http://WINDOWS_HOST_OR_IP:9222/json/version
|
|
curl http://WINDOWS_HOST_OR_IP:9222/json/list
|
|
```
|
|
|
|
Good result:
|
|
|
|
- `/json/version` returns JSON with Browser / Protocol-Version metadata
|
|
- `/json/list` returns JSON (an empty array is fine if no pages are open)
|
|
|
|
If this fails, Windows is not exposing the port to WSL2 yet, the address is
|
|
wrong for the WSL2 side, or firewall/port-forwarding/proxying is missing. Fix
|
|
that before touching OpenClaw config.
|
|
|
|
### Layer 3: configure the correct browser profile
|
|
|
|
Point OpenClaw at the address reachable from WSL2:
|
|
|
|
```json5
|
|
{
|
|
browser: {
|
|
enabled: true,
|
|
defaultProfile: "remote",
|
|
profiles: {
|
|
remote: {
|
|
cdpUrl: "http://WINDOWS_HOST_OR_IP:9222",
|
|
attachOnly: true,
|
|
color: "#00AA00",
|
|
},
|
|
},
|
|
},
|
|
}
|
|
```
|
|
|
|
Notes:
|
|
|
|
- use the WSL2-reachable address, not whatever only works on Windows
|
|
- keep `attachOnly: true` for externally managed browsers
|
|
- `cdpUrl` can be `http://`, `https://`, `ws://`, or `wss://`
|
|
- use HTTP(S) when you want OpenClaw to discover `/json/version`
|
|
- use WS(S) only when the browser provider gives you a direct DevTools
|
|
socket URL
|
|
- test the same URL with `curl` before expecting OpenClaw to succeed
|
|
|
|
### Layer 4: verify the Control UI layer separately
|
|
|
|
Open `http://127.0.0.1:18789/` from Windows, then verify:
|
|
|
|
- the page origin matches what `gateway.controlUi.allowedOrigins` expects
|
|
- token auth or pairing is configured correctly
|
|
- you are not debugging a Control UI auth problem as if it were a browser
|
|
problem
|
|
|
|
Helpful page: [Control UI](/web/control-ui).
|
|
|
|
### Layer 5: verify end-to-end browser control
|
|
|
|
From WSL2:
|
|
|
|
```bash
|
|
openclaw browser --browser-profile remote open https://example.com
|
|
openclaw browser --browser-profile remote tabs
|
|
```
|
|
|
|
Good result:
|
|
|
|
- the tab opens in Windows Chrome
|
|
- `browser tabs` returns the target
|
|
- later actions (`snapshot`, `screenshot`, `navigate`) work from the same
|
|
profile
|
|
|
|
## Common misleading errors
|
|
|
|
| Message | Meaning |
|
|
| --------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
| `control-ui-insecure-auth` | UI origin/secure-context problem, not a CDP transport problem |
|
|
| `token_missing` | auth configuration problem |
|
|
| `pairing required` | device approval problem |
|
|
| `Remote CDP for profile "remote" is not reachable` | WSL2 cannot reach the configured `cdpUrl` |
|
|
| `Browser attachOnly is enabled and CDP websocket for profile "remote" is not reachable` | the HTTP endpoint answered, but the DevTools WebSocket could not be opened |
|
|
| stale viewport / dark-mode / locale / offline overrides after a remote session | run `openclaw browser --browser-profile remote stop` to close the session and release the cached Playwright/CDP connection without restarting the Gateway or the external browser |
|
|
| timeout around `remoteCdpTimeoutMs` (default 1500ms) | usually still CDP reachability, or a slow/unreachable remote endpoint |
|
|
| `No Chrome tabs found for profile="user"` | local Chrome MCP profile selected where no host-local tabs are available |
|
|
|
|
## Fast triage checklist
|
|
|
|
1. Windows: does `curl http://127.0.0.1:9222/json/version` work?
|
|
2. WSL2: does `curl http://WINDOWS_HOST_OR_IP:9222/json/version` work?
|
|
3. OpenClaw config: does `browser.profiles.<name>.cdpUrl` use that exact
|
|
WSL2-reachable address?
|
|
4. Control UI: are you opening `http://127.0.0.1:18789/` instead of a LAN IP?
|
|
5. Are you trying to use `existing-session` across WSL2 and Windows instead
|
|
of raw remote CDP?
|
|
|
|
Verify the Windows Chrome endpoint locally first, verify the same endpoint
|
|
from WSL2 second, and only then debug OpenClaw config or Control UI auth.
|
|
|
|
## Related
|
|
|
|
- [Browser](/tools/browser)
|
|
- [Browser login](/tools/browser-login)
|
|
- [Browser Linux troubleshooting](/tools/browser-linux-troubleshooting)
|