openclaw - 💡(How to fix) Fix process.stdout.write monkey-patch suppresses unrelated concurrent async output [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#83894Fetched 2026-05-20 03:47:21
View on GitHub
Comments
1
Participants
2
Timeline
7
Reactions
1
Timeline (top)
labeled ×5commented ×1unsubscribed ×1

Fix Action

Fix / Workaround

Severity: medium / Confidence: high / Category: bug Triage: confirmed-bug Detected against: openclaw v2026.5.18 (latest stable at time of scan, 2026-05-18) Tooling: clawpatch 0.3.0 + acpx/claude-sonnet-4-5 via Brad Mills protocol

Reasoning

Between the assignment on line 59 and the restore in the finally block, an await suspends the current microtask queue. Any other already-queued promises that resolve during await runDoctorConfigPreflight() will execute with the patched no-op process.stdout.write. This silently drops output from unrelated concurrent async paths (logger flushes, spinner ticks, signal handlers, etc.) without any indication. It also fails to propagate the callback argument that stream.Writable.write callers may pass, meaning any caller checking the boolean return or awaiting a drain event gets incorrect feedback.

Recommendation

Instead of patching the global write method, redirect preflight output through a NullWritable stream injected into runDoctorConfigPreflight, or capture output via a child process / worker_thread, leaving the global stdout intact.

Code Example

const originalStdoutWrite = process.stdout.write.bind(process.stdout);
      const originalSuppressNotes = process.env.OPENCLAW_SUPPRESS_NOTES;
      process.stdout.write = (() => true) as unknown as typeof process.stdout.write;
      process.env.OPENCLAW_SUPPRESS_NOTES = "1";
      try {
        preflightSnapshot = (await runDoctorConfigPreflight()).snapshot;
      } finally {
        process.stdout.write = originalStdoutWrite;
RAW_BUFFERClick to expand / collapse

Severity: medium / Confidence: high / Category: bug Triage: confirmed-bug Detected against: openclaw v2026.5.18 (latest stable at time of scan, 2026-05-18) Tooling: clawpatch 0.3.0 + acpx/claude-sonnet-4-5 via Brad Mills protocol

Evidence

  • src/cli/program/config-guard.ts:57-70 (ensureConfigReady)
const originalStdoutWrite = process.stdout.write.bind(process.stdout);
      const originalSuppressNotes = process.env.OPENCLAW_SUPPRESS_NOTES;
      process.stdout.write = (() => true) as unknown as typeof process.stdout.write;
      process.env.OPENCLAW_SUPPRESS_NOTES = "1";
      try {
        preflightSnapshot = (await runDoctorConfigPreflight()).snapshot;
      } finally {
        process.stdout.write = originalStdoutWrite;

Reasoning

Between the assignment on line 59 and the restore in the finally block, an await suspends the current microtask queue. Any other already-queued promises that resolve during await runDoctorConfigPreflight() will execute with the patched no-op process.stdout.write. This silently drops output from unrelated concurrent async paths (logger flushes, spinner ticks, signal handlers, etc.) without any indication. It also fails to propagate the callback argument that stream.Writable.write callers may pass, meaning any caller checking the boolean return or awaiting a drain event gets incorrect feedback.

Reproduction

Run a CLI invocation that triggers suppressDoctorStdout: true while a background async logger or spinner is active; the logger output is silently swallowed for the duration of the preflight.

Recommendation

Instead of patching the global write method, redirect preflight output through a NullWritable stream injected into runDoctorConfigPreflight, or capture output via a child process / worker_thread, leaving the global stdout intact.

Why existing tests miss this

The suppressDoctorStdout path is not exercised by any test in the provided suite; the context test file covers a different module entirely.

Suggested regression test

Spy on process.stdout.write from a concurrent async task launched before ensureConfigReady is called with suppressDoctorStdout: true, and assert the spy is still called (not suppressed) while the preflight awaits.

Minimum fix scope

The suppressDoctorStdout branch of ensureConfigReady in src/cli/program/config-guard.ts


Standardized clawpatch finding. Persistent in v2026.5.18 (not resolved by upgrading from v2026.5.12). Finding ID: fnd_sig-feat-cli-command-0f69ccd6ad-_3c69639b21.

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…

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 - 💡(How to fix) Fix process.stdout.write monkey-patch suppresses unrelated concurrent async output [1 comments, 2 participants]