Skip to content

fix: explain launch failures caused by running as root - #2634

Merged
OrKoN merged 6 commits into
ChromeDevTools:mainfrom
elcodabra:fix/root-sandbox-launch-error
Sep 15, 2026
Merged

OrKoN merged 6 commits into
ChromeDevTools:mainfrom
elcodabra:fix/root-sandbox-launch-error

Conversation

@elcodabra

Copy link
Copy Markdown
Contributor

Follow-up to #261. That issue was closed by #338, which added --chrome-arg so the sandbox can be disabled explicitly. The flag works, but the failure it fixes is still undiscoverable — you cannot find out that --chrome-arg=--no-sandbox is the answer.

Problem

launch() uses pipe: true. In pipe mode Puppeteer never calls waitForLineOutput(), which is the only place Chrome's stderr makes it into the thrown error. So when Chrome exits at startup with

Running as root without --no-sandbox is not supported. See https://crbug.com/638180.

that line is dropped, and what reaches the MCP client is:

Protocol error (Target.setDiscoverTargets): Target closed

Reproduced on main (v1.8.0) by pointing executablePath at a stub that prints Chrome's message to stderr and exits 1 — exactly the symptom reported in #261. The catch in launch() only recognised The browser is already running.

Fix

Detect the case and rethrow with an explanation. Deliberately not disabling the sandbox automatically, per #261 (comment):

Chrome failed to start: Protocol error (Target.setDiscoverTargets): Target closed

chrome-devtools-mcp is running as root and Chrome does not start as root unless its
sandbox is disabled (https://crbug.com/638180). Prefer running chrome-devtools-mcp as
a non-root user. If that is not possible, for example in a container, pass
--chrome-arg=--no-sandbox. That disables the Chrome sandbox, so only do it for content
you trust.

Notes on the shape of the check:

  • It runs only on a failed launch, so root with a properly installed setuid sandbox is unaffected.
  • The original error is kept in the message and as cause, so an unrelated failure under root is never masked or mislabelled.
  • --no-sandbox present in the args short-circuits it: root is then not what stopped Chrome.
  • --disable-setuid-sandbox and --no-sandbox-and-elevated do not count as opting out — Chrome's zygote check requires --no-sandbox specifically. Covered by a test.
  • On Windows process.getuid is undefined, so the check is a no-op.

Also adds a "Running as root" section to docs/troubleshooting.md, next to the existing "Operating system sandboxes".

Testing

Five unit tests in tests/browser.test.ts covering root / non-root / no-uid platforms, the already-opted-out args, and the near-miss args above.

The pre-existing integration tests in that file cannot run in my environment — Chrome reports No usable sandbox! ... AppArmor userns restrictions there, on a clean checkout as well as with this change.

Chrome refuses to start as root unless its sandbox is disabled and only
says so on its stderr. We launch with `pipe: true`, so Puppeteer never
waits for a line of browser output and that stderr is dropped: the
failure reaches the client as an opaque
`Protocol error (Target.setDiscoverTargets): Target closed`, with no
hint that `--chrome-arg=--no-sandbox` is what gets past it.

Detect the case in `launch()` and rethrow with an explanation. The
sandbox is still never disabled automatically, and the original error is
kept both in the message and as `cause` so unrelated failures under root
are not masked.

Fixes ChromeDevTools#261
@google-cla

google-cla Bot commented Sep 1, 2026

Copy link
Copy Markdown

Thanks for your pull request! It looks like this may be your first contribution to a Google open source project. Before we can look at your pull request, you'll need to sign a Contributor License Agreement (CLA).

View this failed invocation of the CLA check for more information.

For the most up to date status, view the checks section at the bottom of the pull request.

@elcodabra

Copy link
Copy Markdown
Contributor Author

@googlebot I signed it!

Comment thread docs/troubleshooting.md Outdated
Address review feedback: recommending --chrome-arg=--no-sandbox risks
users reaching for it for unrelated launch failures and silently losing
the sandbox. Both the runtime error and the troubleshooting section now
say to run as a non-root user and link Puppeteer's "Setting up Chrome
Linux sandbox" guide instead.
@OrKoN
OrKoN self-requested a review September 8, 2026 13:43
@elcodabra
elcodabra force-pushed the fix/root-sandbox-launch-error branch from 6535e61 to c6b0fce Compare September 8, 2026 16:50
@OrKoN
OrKoN enabled auto-merge September 15, 2026 10:32
@OrKoN
OrKoN added this pull request to the merge queue Sep 15, 2026
Merged via the queue into ChromeDevTools:main with commit 9d29223 Sep 15, 2026
20 checks passed
pull Bot pushed a commit to oogalieboogalie/chrome-devtools-mcp that referenced this pull request Sep 23, 2026
🤖 I have created a release *beep* *boop*
---


##
[1.10.0](ChromeDevTools/chrome-devtools-mcp@chrome-devtools-mcp-v1.9.0...chrome-devtools-mcp-v1.10.0)
(2026-09-23)


### 🎉 Features

* add css formatter class
([ChromeDevTools#2707](ChromeDevTools#2707))
([f0b5fa4](ChromeDevTools@f0b5fa4))
* add get_css_style tool
([ChromeDevTools#2612](ChromeDevTools#2612))
([4454ae0](ChromeDevTools@4454ae0))
* **performance:** chunked trace buffer parser for large recordings
([ChromeDevTools#2721](ChromeDevTools#2721))
([23b9a48](ChromeDevTools@23b9a48))
* set default pageSize and pageIdx for get_css_styles tool
([ChromeDevTools#2799](ChromeDevTools#2799))
([dc9d14d](ChromeDevTools@dc9d14d))
* support config file
([ChromeDevTools#2661](ChromeDevTools#2661))
([314a5fa](ChromeDevTools@314a5fa))
* **telemetry:** persist date of the last tool call.
([ChromeDevTools#2705](ChromeDevTools#2705))
([c54a493](ChromeDevTools@c54a493))
* **telemetry:** recording a sanitized version of the client name
([ChromeDevTools#2757](ChromeDevTools#2757))
([55fbc57](ChromeDevTools@55fbc57))
* **telemetry:** report hermes client usage.
([ChromeDevTools#2703](ChromeDevTools#2703))
([fb47e6c](ChromeDevTools@fb47e6c))
* update css formatter class to add AtRule, PositionTryRule,
PropertyRule, FunctionRule
([ChromeDevTools#2717](ChromeDevTools#2717))
([d4a0620](ChromeDevTools@d4a0620))
* update css formatter class to add inherited rules
([ChromeDevTools#2715](ChromeDevTools#2715))
([3d7e7bb](ChromeDevTools@3d7e7bb))
* update css formatter class to add matched rules
([ChromeDevTools#2713](ChromeDevTools#2713))
([8c8616f](ChromeDevTools@8c8616f))
* update css formatter class to add pseudo element
([ChromeDevTools#2716](ChromeDevTools#2716))
([df1469a](ChromeDevTools@df1469a))
* update css formatter to add keyframes rules
([ChromeDevTools#2718](ChromeDevTools#2718))
([cdc365c](ChromeDevTools@cdc365c))


### 🛠️ Fixes

* bound ConsoleCollector retention per navigation
([ChromeDevTools#2773](ChromeDevTools#2773))
([e98a3ca](ChromeDevTools@e98a3ca))
* **cli:** forward explicit false options on start
([ChromeDevTools#2702](ChromeDevTools#2702))
([d9a8cb6](ChromeDevTools@d9a8cb6))
* **config:** preserve raw values for config coercion
([ChromeDevTools#2747](ChromeDevTools#2747))
([906c83b](ChromeDevTools@906c83b))
* don't log Puppeteer logs to file unless requested
([ChromeDevTools#2743](ChromeDevTools#2743))
([4fbfbc4](ChromeDevTools@4fbfbc4))
* explain launch failures caused by running as root
([ChromeDevTools#2634](ChromeDevTools#2634))
([9d29223](ChromeDevTools@9d29223))
* handle JavaScript dialogs opened during input tool actions
([ChromeDevTools#2794](ChromeDevTools#2794))
([266112b](ChromeDevTools@266112b))
* **performance:** prevent memory leak by scoping trace engine model per
parse
([ChromeDevTools#2720](ChromeDevTools#2720))
([d05cbc0](ChromeDevTools@d05cbc0))
* preserve console history across same-document navigations
([ChromeDevTools#2676](ChromeDevTools#2676))
([aa25562](ChromeDevTools@aa25562))
* preserve underlying error message in input tool actions
([ChromeDevTools#2792](ChromeDevTools#2792))
([6e47dbb](ChromeDevTools@6e47dbb))
* set emulatedUserAgent and use finalDisplayedUrl in lighthouse_audit
([ChromeDevTools#2795](ChromeDevTools#2795))
([941f82a](ChromeDevTools@941f82a))
* timout in WaitForHelper.ts
([ChromeDevTools#2772](ChromeDevTools#2772))
([dc1d055](ChromeDevTools@dc1d055))


### 📄 Documentation

* add FLUJO client configuration
([ChromeDevTools#2690](ChromeDevTools#2690))
([65a679e](ChromeDevTools@65a679e))
* fix categories not being configured correclty
([ChromeDevTools#2807](ChromeDevTools#2807))
([2250cdc](ChromeDevTools@2250cdc))
* fix defaults for non-boolean values
([ChromeDevTools#2744](ChromeDevTools#2744))
([342d243](ChromeDevTools@342d243))
* update page routing option name
([ChromeDevTools#2748](ChromeDevTools#2748))
([8939965](ChromeDevTools@8939965))
* update SKILL for chrome-devtools to use get_css_styles tool
([ChromeDevTools#2760](ChromeDevTools#2760))
([421011e](ChromeDevTools@421011e))


### 🏗️ Refactor

* disable tools instead of not registering them
([ChromeDevTools#2636](ChromeDevTools#2636))
([b455469](ChromeDevTools@b455469))
* extract browser in a BrowserManager class
([ChromeDevTools#2787](ChromeDevTools#2787))
([3228f44](ChromeDevTools@3228f44))
* migrate the MCP SDK to v2
([ChromeDevTools#2408](ChromeDevTools#2408))
([da3c406](ChromeDevTools@da3c406))
* move comments formatting to CommentFormatter class
([ChromeDevTools#2719](ChromeDevTools#2719))
([e3cded0](ChromeDevTools@e3cded0))
* prepare for SDK v2
([ChromeDevTools#2771](ChromeDevTools#2771))
([61780c7](ChromeDevTools@61780c7))
* simplify our gen scritps
([ChromeDevTools#2793](ChromeDevTools#2793))
([5068584](ChromeDevTools@5068584))
* unify call type and ensure typesafety
([ChromeDevTools#2659](ChromeDevTools#2659))
([882f93e](ChromeDevTools@882f93e))

---
This PR was generated with [Release
Please](https://github.com/googleapis/release-please). See
[documentation](https://github.com/googleapis/release-please#release-please).
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants