openclaw - ✅(Solved) Fix [Bug]: browser control spawn chrome without setting env['DISPLAY'] = ':0' so chrome failed to initialize [3 pull requests, 1 comments, 2 participants]

Official PRs (…)
ON THIS PAGE

Recommended Tools

×6

Utilities matched from this issue’s tags and category — try them while you read without losing context.

GitHub issue graph ai analysis

Paste a GitHub issue URL. We fetch that issue, discover linked issues from bodies/comments/timeline, collect linked pull requests, and produce a structured English report.

The report is written in English Markdown for sharing and archival.

Helpful · Quick feedback

Loading…
GitHub stats
openclaw/openclaw#64464Fetched 2026-04-11 06:14:48
View on GitHub
Comments
1
Participants
2
Timeline
8
Reactions
0
Author
Participants
Timeline (top)
cross-referenced ×3referenced ×3commented ×1labeled ×1

Browser tool should pass env setting DISPLAY: ':0' to chrome in wsl2. This won't happen in headless mode of browser

Error Message

GatewayClientRequestError: Error: Failed to start Chrome CDP on port 18800 for profile "openclaw". [26201:26201:0411/022052.859430:ERROR:ui/ozone/platform/x11/ozone_platform_x11.cc:256] Missing X server or $DISPLAY [26201:26201:0411/022052.859469:ERROR:ui/aura/env.cc:246] The platform failed to initialize. Exiting.

Root Cause

Browser tool should pass env setting DISPLAY: ':0' to chrome in wsl2. This won't happen in headless mode of browser

Fix Action

Fixed

PR fix notes

PR #64470: fix(browser): set DISPLAY env var for WSL2 Chrome launches

Description (problem / solution / changelog)

Fix for Issue #64464

Chrome fails to start in WSL2 because the DISPLAY environment variable is not set. Chrome needs DISPLAY to connect to the X server running on Windows.

Changes

  • Added WSL2 detection function that checks:
    • /proc/sys/fs/binfmt_misc/WSLInterop file existence
    • process.release?.name === "wsl"
  • When WSL2 is detected, sets DISPLAY=":0" in the Chrome spawn environment

This allows openclaw browser start to work in WSL2 without manually setting the DISPLAY environment variable.

Testing

Tested on WSL2 with Chrome installed on Windows host.

Changed files

  • extensions/browser/src/browser/chrome.ts (modified, +11/-0)

PR #64547: fix(browser): set DISPLAY fallback for non-headless Chrome on Linux/WSL2

Description (problem / solution / changelog)

Summary

Fixes #64464 — Non-headless Chrome on WSL2 fails with Missing X server or $DISPLAY because the environment variable is unset.

Root Cause

WSL2 (especially with WSLg) often doesn't export DISPLAY to all shell contexts. The Chrome spawn in launchOpenClawChrome() passes process.env, which lacks DISPLAY. Chrome's X11/Ozone platform then fails:

ERROR:ui/ozone/platform/x11/ozone_platform_x11.cc:256] Missing X server or $DISPLAY
ERROR:ui/aura/env.cc:246] The platform failed to initialize. Exiting.

Fix

When all three conditions are met, fall back to DISPLAY=:0:

  1. Platform is Linux
  2. Headless mode is disabled
  3. process.env.DISPLAY is unset

:0 is the standard default for X11/Xwayland/WSLg displays. If the user has DISPLAY set, their value takes precedence (...process.env spread comes first).

No-op for other environments

  • Headless mode: skip (no display needed)
  • macOS/Windows: skip (no DISPLAY concept)
  • Linux with DISPLAY set: skip (existing value preserved)

Changed files

  • extensions/browser/src/browser/chrome.ts (modified, +6/-0)
  • src/auto-reply/reply/reply-media-paths.ts (modified, +13/-0)

PR #64573: fix(browser): inject DISPLAY=:0 fallback when spawning Chrome on Linux

Description (problem / solution / changelog)

Summary

  • Problem: Non-headless Chrome spawned by the browser extension fails to start on Linux/WSL2 with Missing X server or $DISPLAY, because the launch context (WSL2 shell, systemd user unit, launchd agent) did not propagate DISPLAY into the spawned process.
  • Why it matters: WSL2 users with a non-snap Chrome cannot use non-headless browser control at all — the Chrome bootstrap dies before CDP comes up, and the user sees GatewayClientRequestError: Failed to start Chrome CDP on port 18800.
  • What changed: Extracted the Chrome spawn environment into a pure buildChromeSpawnEnv helper and have it inject DISPLAY=:0 only on Linux, only in non-headless mode, and only when the caller has not already set one.
  • What did NOT change (scope boundary): macOS, Windows, headless Chrome, and any launch where DISPLAY is already set in the parent env. No launch args changed. No behavior change for buildOpenClawChromeLaunchArgs.

Change Type (select all)

  • Bug fix
  • Feature
  • Refactor required for the fix
  • Docs
  • Security hardening
  • Chore/infra

Scope (select all touched areas)

  • Gateway / orchestration
  • Skills / tool execution
  • Auth / tokens
  • Memory / storage
  • Integrations
  • API / contracts
  • UI / DX
  • CI/CD / infra

Linked Issue/PR

  • Closes #64464
  • Related #
  • This PR fixes a bug or regression

Root Cause (if applicable)

  • Root cause: launchOpenClawChrome in extensions/browser/src/browser/chrome.ts builds a spawn env that starts from process.env and explicitly overrides HOME. When the parent process has no DISPLAY (common in WSL2 invocations that did not inherit WSLg's env, systemd user units, or the gateway running as a daemon), the spawned Chrome has no X display and the ozone/X11 platform initialization aborts before CDP is reachable.
  • Missing detection / guardrail: Headless mode masked this because --headless=new does not touch X11, so the bug only surfaces for users who explicitly set headless: false. There was no unit test covering the spawn env — only the launch args were tested.
  • Contributing context (if known): Reporter noted the exact fix in the issue, including the file and line (extensions/browser/src/browser/chrome.ts inside the spawnOnce closure of launchOpenClawChrome).

Regression Test Plan (if applicable)

  • Coverage level that should have caught this:
    • Unit test
    • Seam / integration test
    • End-to-end test
    • Existing coverage already sufficient
  • Target test or file: extensions/browser/src/browser/chrome.spawn-env.test.ts (new)
  • Scenario the test should lock in: buildChromeSpawnEnv must inject DISPLAY=:0 on Linux in non-headless mode when the base env has none, and must leave DISPLAY unchanged in every other combination (Linux+headless, Linux+existing DISPLAY, macOS, Windows).
  • Why this is the smallest reliable guardrail: The spawn env is pure data assembly — a per-platform truth table is the cheapest test that fully covers the rule set, and it cannot regress silently because it does not depend on a real Chrome binary.
  • Existing test that already covers this (if any): None. chrome.launch-args.test.ts covered buildOpenClawChromeLaunchArgs but not the env bag.
  • If no new test is added, why not: N/A — a new test file is added.

User-visible / Behavior Changes

WSL2 and Linux users launching non-headless Chrome without DISPLAY in their env will now succeed (previously failed). No change for users who already had DISPLAY set, nor for macOS/Windows users, nor for headless Chrome.

Diagram (if applicable)

Before (Linux non-headless, no DISPLAY in parent env):
  spawn(chrome, { env: { ...process.env, HOME } })
    -> chrome stderr: "Missing X server or $DISPLAY"
    -> CDP never comes up -> "Failed to start Chrome CDP on port 18800"

After:
  spawn(chrome, { env: buildChromeSpawnEnv({ base: process.env, platform, headless, home }) })
    -> env includes DISPLAY=":0" (only injected on Linux + non-headless + unset)
    -> chrome initializes X11 ozone platform -> CDP ready

Security Impact (required)

  • New permissions/capabilities? No
  • Secrets/tokens handling changed? No
  • New/changed network calls? No
  • Command/tool execution surface changed? No — same spawn(exe.path, args, ...) call, same args, only the env bag is assembled via a helper.
  • Data access scope changed? No

Repro + Verification

Environment

  • OS: WSL2 Ubuntu (per reporter); tests run on Windows 11 host, Node 22
  • Runtime/container: Native host Chrome (non-snap)
  • Model/provider: N/A — this is browser-subprocess plumbing
  • Integration/channel: browser extension (extensions/browser)
  • Relevant config: browser.headless = false, no DISPLAY in parent env

Steps

  1. On WSL2 with non-snap Chrome installed, start the browser extension with headless: false.
  2. Observe Chrome fails to come up, stderr contains Missing X server or $DISPLAY.
  3. Apply this patch; repeat — Chrome starts, CDP becomes reachable on 18800.

Expected

Chrome starts; CDP handshake succeeds.

Actual (before the fix)

GatewayClientRequestError: Failed to start Chrome CDP on port 18800 for profile "openclaw". with Missing X server or $DISPLAY in stderr.

Evidence

  • Failing test/log before + passing after
  • Trace/log snippets
  • Screenshot/recording
  • Perf numbers (if relevant)

New test file results:

 RUN  v4.1.4
 Test Files  2 passed (2)
      Tests  7 passed (7)

Tests run:

  • chrome.spawn-env.test.ts: 6 cases (Linux non-headless injects, existing DISPLAY preserved, Linux headless no-op, macOS no-op, Windows no-op, HOME pinned on all platforms).
  • chrome.launch-args.test.ts: existing smoke test still green.

oxlint on the touched files: Found 0 warnings and 0 errors.

Human Verification (required)

  • Verified scenarios:
    • Ran vitest against the new and existing browser test files locally — all 7 pass.
    • Ran oxlint against chrome.ts and the new test file — clean.
    • Walked the spawnOnce closure to confirm resolved.headless is in scope at the call site.
    • Confirmed buildOpenClawChromeLaunchArgs already gates --headless=new on resolved.headless, so headless branches cannot observe the DISPLAY injection.
  • Edge cases checked:
    • DISPLAY="" (empty string) in parent env — treated as unset and the :0 fallback is applied. Empty DISPLAY is not a valid X display, so this is the intended outcome.
    • User-set DISPLAY=:1 (remote X) — preserved, never clobbered.
  • What I did NOT verify: I did not spin up a real WSL2 + Chrome session end-to-end — the reporter's trace already demonstrates the failure mode and the fix matches their suggested remediation. I relied on unit tests for the env-assembly logic.

Review Conversations

  • I replied to or resolved every bot review conversation I addressed in this PR.
  • I left unresolved only the conversations that still need reviewer or maintainer judgment.

Compatibility / Migration

  • Backward compatible? Yes
  • Config/env changes? No
  • Migration needed? No
  • If yes, exact upgrade steps: N/A

Risks and Mitigations

  • Risk: Injected DISPLAY=:0 on a Linux host that has no X server at all (e.g. a headless Linux box misconfigured with headless: false) would not suddenly make Chrome work — it would still fail.
    • Mitigation: The failure mode is identical to today (Chrome exits with an X error), so this is a strict no-regression. Headless users (the correct path for fully headless boxes) are untouched.
  • Risk: A user who relies on DISPLAY being absent for some downstream behavior would see a surprise.
    • Mitigation: The injection is scoped to the Chrome spawn env only; it does not mutate process.env of the parent, and it only activates when DISPLAY is already absent from the base env.

Changed files

  • extensions/browser/src/browser/chrome.spawn-env.test.ts (added, +83/-0)
  • extensions/browser/src/browser/chrome.ts (modified, +39/-5)
RAW_BUFFERClick to expand / collapse

Bug type

Crash (process/app exits or hangs)

Beta release blocker

No

Summary

Browser tool should pass env setting DISPLAY: ':0' to chrome in wsl2. This won't happen in headless mode of browser

Steps to reproduce

WSL2, standard activate broser tool and google chrome which is not a snap version, headless: false openclaw browser start

Expected behavior

spawn chrome window

Actual behavior

Output: GatewayClientRequestError: Error: Failed to start Chrome CDP on port 18800 for profile "openclaw". Chrome stderr: [26201:26201:0411/022052.859430:ERROR:ui/ozone/platform/x11/ozone_platform_x11.cc:256] Missing X server or $DISPLAY [26201:26201:0411/022052.859469:ERROR:ui/aura/env.cc:246] The platform failed to initialize. Exiting.

OpenClaw version

2026.4.9

Operating system

WSL ubuntu

Install method

No response

Model

no relationship with model

Provider / routing chain

openclaw -> browser

Additional provider/model setup details

No response

Logs, screenshots, and evidence

Impact and severity

No response

Additional information

Fix this bug here: line 336 of extensions/browser/src/browser/chrome.ts add DISPLAY: ':0'

extent analysis

TL;DR

Set the DISPLAY environment variable to ':0' when launching Chrome in WSL2 to resolve the missing X server error.

Guidance

  • The error message indicates a missing X server or $DISPLAY variable, which is required for Chrome to launch in non-headless mode.
  • To fix this, you need to pass the DISPLAY environment variable to Chrome when launching it from the browser tool.
  • Modify the chrome.ts file at the specified line to include the DISPLAY environment variable, for example: env: { DISPLAY: ':0' }.
  • Verify that the DISPLAY variable is set correctly by checking the environment variables passed to the Chrome process.

Example

// In chrome.ts, add the DISPLAY environment variable
const chromeOptions = {
  // ... other options ...
  env: {
    DISPLAY: ':0'
  }
};

Notes

This fix assumes that the X server is running and accessible on the specified display (:0). If the X server is not running or not configured correctly, additional setup may be required.

Recommendation

Apply the workaround by modifying the chrome.ts file to include the DISPLAY environment variable, as this should resolve the immediate issue and allow Chrome to launch in non-headless mode.

Vote matrix · Quick signals

Works
Did the solution work? Tap to confirm.
Easy Fix
Was it a quick fix?
Time Saver
Did it save you time?
Blocking
Was it severely blocking?
Common Issue
Are others likely hitting this too?
Flaky / Intermittent
Is it intermittent?
Verified / Reproducible
Can you reproduce it reliably?
Loading…

FAQ

Expected behavior

spawn chrome window

Still need to ship something?

×6

Another batch ranked right after the header list — different links, same matching logic.

Back to top recommendations

TRENDING

openclaw - ✅(Solved) Fix [Bug]: browser control spawn chrome without setting env['DISPLAY'] = ':0' so chrome failed to initialize [3 pull requests, 1 comments, 2 participants]