Skip to content

fix(browser): prevent stdio buffer blocking in Docker environments#27899

Open
stephenschoettler wants to merge 3 commits intoopenclaw:mainfrom
stephenschoettler:fix/docker-browser-stdio
Open

fix(browser): prevent stdio buffer blocking in Docker environments#27899
stephenschoettler wants to merge 3 commits intoopenclaw:mainfrom
stephenschoettler:fix/docker-browser-stdio

Conversation

@stephenschoettler
Copy link
Copy Markdown
Contributor

Fixes browser automation failures in Docker by changing Chrome spawn configuration from stdio: "pipe" to stdio: ["ignore", "ignore", "ignore"].

Problem: When using stdio: "pipe", Chrome's stdout/stderr buffers fill up (~64KB limit) and block the process, preventing CDP from becoming reachable within the timeout window.

Solution: Discard Chrome's output instead of piping it. The codebase doesn't consume Chrome's stdout/stderr anyway, so there's no functional loss.

Result: CDP becomes reachable within ~500ms of Chrome startup in Docker.

Tested manually in Docker with Playwright Chromium on Debian 12.

@openclaw-barnacle openclaw-barnacle bot added gateway Gateway runtime size: XS labels Feb 26, 2026
@greptile-apps
Copy link
Copy Markdown
Contributor

greptile-apps bot commented Feb 26, 2026

Greptile Summary

This PR contains two separate bug fixes:

  1. Browser stdio fix (chrome.ts): Changed Chrome spawn configuration from stdio: "pipe" to stdio: ["ignore", "ignore", "ignore"] to prevent buffer blocking in Docker environments. The codebase doesn't consume Chrome's stdout/stderr streams anywhere, so discarding them is safe and resolves the CDP timeout issue.

  2. Null guard fix (usage.ts, session-cost-usage.ts): Added optional chaining and nullish coalescing to usage sort comparators to prevent crashes when totals is undefined. The fix prevents "Cannot read properties of undefined" errors in production.

Note: The PR title only mentions the browser fix, but includes the unrelated usage fix as well. According to the project's guidelines (CLAUDE.md), unrelated changes should typically be in separate PRs. Both fixes are valid, but bundling them may make the PR history harder to track.

Confidence Score: 4/5

  • This PR is safe to merge with low risk
  • Both fixes address real bugs and are technically correct. The stdio change is well-justified and doesn't break any existing functionality (verified that Chrome stdout/stderr are unused). The null guards are defensive programming that prevent actual crashes. Score is 4 instead of 5 due to: (1) bundling two unrelated fixes in one PR, which goes against project guidelines, and (2) missing test coverage for the fixes.
  • No files require special attention

Last reviewed commit: 200f8c0

@openclaw-barnacle
Copy link
Copy Markdown

This pull request has been automatically marked as stale due to inactivity.
Please add updates or it will be closed.

@openclaw-barnacle openclaw-barnacle bot added the stale Marked as stale due to inactivity label Mar 4, 2026
@stephenschoettler
Copy link
Copy Markdown
Contributor Author

Note: the install-smoke failure blocking PR #31192 is the same src/browser/chrome.ts stdin type mismatch that this PR fixes. Merging this PR (#27899) should unblock #31192's CI as well.

@openclaw-barnacle openclaw-barnacle bot removed the stale Marked as stale due to inactivity label Mar 5, 2026
@stephenschoettler stephenschoettler force-pushed the fix/docker-browser-stdio branch 2 times, most recently from 7ef53df to bd8bda0 Compare March 22, 2026 22:01
Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: bd8bda0c62

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".


return spawn(exe.path, args, {
stdio: "pipe",
stdio: ["ignore", "ignore", "ignore"],
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Keep Chrome stderr piped for startup failures

When Chrome exits before CDP comes up — for example because a container is missing shared libraries or still needs browser.noSandbox: true — this change removes the only actionable diagnostics we surface. launchOpenClawChrome still installs proc.stderr?.on("data") and includes stderrHint in the thrown error (src/browser/chrome.ts:379-413), but with fd 2 set to "ignore" proc.stderr is always null, so these failures now degrade to a generic timeout. Because stderr was already being drained, only stdout needed to stop piping to avoid the Docker backpressure issue.

Useful? React with 👍 / 👎.

@stephenschoettler stephenschoettler force-pushed the fix/docker-browser-stdio branch from bd8bda0 to ef829e8 Compare March 23, 2026 00:22
Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: ef829e8ebf

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

// the tuple overload resolution varies across @types/node versions.
return spawn(exe.path, args, {
stdio: "pipe",
stdio: ["ignore", "ignore", "pipe"],
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Ignore bootstrap stderr too to fix first-run Docker launches

When needsBootstrap is true (first run, or after the profile files are missing), launchOpenClawChrome() reuses spawnOnce() for the bootstrap process but does not attach a data listener until the later “real” launch. Because fd 2 is still pipe here, a noisy Chromium startup in containers can fill bootstrap.stderr and stall before Local State/Preferences are created, so the Docker deadlock this patch is fixing still reproduces on fresh profiles. Discarding or draining stderr for the bootstrap run would make the fix cover first-run launches as well.

Useful? React with 👍 / 👎.

Prevents crash when totals is undefined in byModel/byProvider/byAgent
sort comparators. Fixes 'Cannot read properties of undefined (reading
totalTokens)' crash that causes context overflow in active sessions.
… compat

The stdio tuple overload resolves differently across @types/node versions
(v20 vs v24/v25). Cast the spawn() result to ChildProcessWithoutNullStreams
to ensure proc.stderr?.on/off type-checks regardless of installed @types/node.
@stephenschoettler stephenschoettler force-pushed the fix/docker-browser-stdio branch from ef829e8 to 036d09f Compare March 23, 2026 00:47
Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 036d09fbb9

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

// the tuple overload resolution varies across @types/node versions.
return spawn(exe.path, args, {
stdio: "pipe",
stdio: ["ignore", "ignore", "pipe"],
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Keep draining stderr after Chrome startup

When Chrome reaches CDP readiness we remove the only stderr listener (src/browser/chrome.ts:428-430), but this change still leaves fd 2 configured as "pipe". The comment at src/browser/chrome.ts:392-393 already notes that long-lived Chrome processes can emit periodic warnings; in Docker/root setups those warnings will now accumulate in the undrained pipe until it fills, at which point later writes block again. So this only fixes startup backpressure on stdout — long-running browser sessions are still vulnerable to the same stdio saturation issue once enough stderr is produced.

Useful? React with 👍 / 👎.

@openclaw-barnacle
Copy link
Copy Markdown

This pull request has been automatically marked as stale due to inactivity.
Please add updates or it will be closed.

@openclaw-barnacle openclaw-barnacle bot added the stale Marked as stale due to inactivity label Mar 31, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

gateway Gateway runtime size: XS stale Marked as stale due to inactivity

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant