fix(browser): include Chrome stderr and sandbox hint in CDP startup error (#29355)

* fix(browser): include Chrome stderr and sandbox hint in CDP startup error (#29312)

When Chrome fails to start and CDP times out, the error message previously
contained no diagnostic information, making it impossible to determine why
Chrome couldn't start (e.g. missing --no-sandbox in containers, GPU issues,
shared memory errors).

This change:
- Collects Chrome's stderr output and includes up to 2000 chars in the error
- On Linux, if noSandbox is not set, appends a hint to try browser.noSandbox: true

Closes #29312

* chore(browser): format chrome startup diagnostics

* fix(browser): detach stderr listener after Chrome starts to prevent memory leak

Named the anonymous listener so it can be removed via proc.stderr.off()
once CDP is confirmed reachable. Also clears the stderrChunks array on
success so the buffered data is eligible for GC.

Fixes the unbounded memory growth reported in code review: a long-lived
Chrome process emitting periodic warnings would keep appending to
stderrChunks indefinitely since the listener was never removed.

Addresses review comment from chatgpt-codex-connector on PR #29355.

* changelog: note cdp startup diagnostics improvement

---------

Co-authored-by: Vincent Koc <vincentkoc@ieee.org>
Co-authored-by: 派尼尔 <painier@openclaw.ai>
This commit is contained in:
Veast
2026-03-02 15:08:52 +08:00
committed by GitHub
parent cb491dfde5
commit 281494ae52
2 changed files with 22 additions and 1 deletions

View File

@@ -285,6 +285,16 @@ export async function launchOpenClawChrome(
}
const proc = spawnOnce();
// Collect stderr for diagnostics in case Chrome fails to start.
// The listener is removed on success to avoid unbounded memory growth
// from a long-lived Chrome process that emits periodic warnings.
const stderrChunks: Buffer[] = [];
const onStderr = (chunk: Buffer) => {
stderrChunks.push(chunk);
};
proc.stderr?.on("data", onStderr);
// Wait for CDP to come up.
const readyDeadline = Date.now() + 15_000;
while (Date.now() < readyDeadline) {
@@ -295,16 +305,26 @@ export async function launchOpenClawChrome(
}
if (!(await isChromeReachable(profile.cdpUrl, 500))) {
const stderrOutput = Buffer.concat(stderrChunks).toString("utf8").trim();
const stderrHint = stderrOutput ? `\nChrome stderr:\n${stderrOutput.slice(0, 2000)}` : "";
const sandboxHint =
process.platform === "linux" && !resolved.noSandbox
? "\nHint: If running in a container or as root, try setting browser.noSandbox: true in config."
: "";
try {
proc.kill("SIGKILL");
} catch {
// ignore
}
throw new Error(
`Failed to start Chrome CDP on port ${profile.cdpPort} for profile "${profile.name}".`,
`Failed to start Chrome CDP on port ${profile.cdpPort} for profile "${profile.name}".${sandboxHint}${stderrHint}`,
);
}
// Chrome started successfully — detach the stderr listener and release the buffer.
proc.stderr?.off("data", onStderr);
stderrChunks.length = 0;
const pid = proc.pid ?? -1;
log.info(
`🦞 openclaw browser started (${exe.kind}) profile "${profile.name}" on 127.0.0.1:${profile.cdpPort} (pid ${pid})`,