Skip to content

fix(hooks): suppress unhandled stdout/stderr stream errors in gmail watcher#100519

Merged
openclaw-clownfish[bot] merged 4 commits into
openclaw:mainfrom
cxbAsDev:fix/gmail-watcher-stream-errors
Jul 6, 2026
Merged

fix(hooks): suppress unhandled stdout/stderr stream errors in gmail watcher#100519
openclaw-clownfish[bot] merged 4 commits into
openclaw:mainfrom
cxbAsDev:fix/gmail-watcher-stream-errors

Conversation

@cxbAsDev

@cxbAsDev cxbAsDev commented Jul 6, 2026

Copy link
Copy Markdown
Contributor

Re-submission of #100414, which was closed automatically when the active PR queue was limited. The branch has been rebased onto the latest main.

What Problem This Solves

spawnGogServe attaches data listeners to child.stdout and child.stderr, but does not attach error listeners. If either stream emits an error event, the unhandled error can crash the OpenClaw process even though the watcher startup itself would otherwise succeed.

Why This Change Was Made

Add error handlers to both stdout and stderr streams before the data handlers. The handlers log the error and continue, mirroring the existing child.on("error", ...) logging pattern.

User Impact

More robust Gmail watcher startup: transient stream read errors no longer crash the process.

Evidence

Regression test:

node scripts/run-vitest.mjs src/hooks/gmail-watcher.test.ts
Test Files  1 passed (1)
     Tests  9 passed (9)

Real behavior proof:

node_modules/.bin/tsx scripts/proof/gmail-watcher-stream-errors.mts

The proof prepends a fake gog binary to PATH, starts the real startGmailWatcher, then emits real error events on the serve child's stdout and stderr streams. With the fix the watcher still starts and the errors are logged:

[gmail-watcher] gmail watcher started for [email protected] (renew every 1m)
Watcher started successfully.

PASS: stream errors were caught and startGmailWatcher still resolved.
...
[gmail-watcher] gog stdout error: Error: gog stdout read failed
[gmail-watcher] gog stderr error: Error: gog stderr read failed

@cxbAsDev

cxbAsDev commented Jul 6, 2026

Copy link
Copy Markdown
Contributor Author

Rebased onto latest main and verified locally.

Combined test run covering all five re-submitted stream-error fixes:

node scripts/run-vitest.mjs \
  src/hooks/gmail-watcher.test.ts \
  src/secrets/resolve.test.ts \
  src/agents/utils/child-process.test.ts \
  src/agents/sandbox/docker.test.ts \
  src/transcripts/store.test.ts

Results:

  • src/transcripts/store.test.ts — 6 tests passed
  • src/hooks/gmail-watcher.test.ts — 9 tests passed
  • src/secrets/resolve.test.ts — 26 tests passed
  • src/agents/utils/child-process.test.ts — 4 tests passed
  • src/agents/sandbox/docker.test.ts — 4 tests passed

Total: 49 tests passed across 4 Vitest shards in ~45s.

@clawsweeper

clawsweeper Bot commented Jul 6, 2026

Copy link
Copy Markdown
Contributor

Codex review: needs maintainer review before merge. Reviewed July 6, 2026, 2:07 AM ET / 06:07 UTC.

Summary
The PR adds stdout/stderr error listeners to spawnGogServe, a regression test, and a local proof script for Gmail watcher stream errors.

PR surface: Source +6, Tests +27, Other +102. Total +135 across 3 files.

Reproducibility: yes. source-reproducible: current main pipes Gmail watcher stdout/stderr and only listens for data plus child process errors; the PR test/proof emit stream error events through that path. I did not execute the proof locally in this read-only review.

Review metrics: none identified.

Stored data model
Persistent data-model change detected: serialized state: scripts/proof/gmail-watcher-stream-errors.mts. Confirm migration or upgrade compatibility proof before merge.

Root-cause cluster
Relationship: canonical
Canonical: #100519
Summary: This PR is the canonical open item for the Gmail watcher stdout/stderr stream-error fix; the earlier same-author submission was queue-closed, while nearby Gmail watcher PRs address distinct watcher lifecycle failures.

Members:

Proposal only: this assessment does not dispatch repair, suppress jobs, mutate sibling items, close, or merge anything.

Merge readiness
Overall: 🐚 platinum hermit
Proof: 🦞 diamond lobster
Patch quality: 🐚 platinum hermit
Result: ready for maintainer review.

Overall follows the weaker of proof and patch quality, so missing proof can cap an otherwise strong patch.

Rank-up moves:

  • none.

Next step before merge

  • No ClawSweeper repair job is needed; the patch has no blocking findings and the remaining action is ordinary maintainer review and merge gating.

Security
Cleared: Cleared: the diff adds local process stream error handling, a regression test, and a proof script without new dependencies, downloads, secrets, permissions, or publishing changes.

Review details

Best possible solution:

Land the narrow stream error handlers with the regression test and proof script after maintainer approval; no broader Gmail watcher refactor is needed for this failure mode.

Do we have a high-confidence way to reproduce the issue?

Yes, source-reproducible: current main pipes Gmail watcher stdout/stderr and only listens for data plus child process errors; the PR test/proof emit stream error events through that path. I did not execute the proof locally in this read-only review.

Is this the best way to solve the issue?

Yes, this is the best narrow fix: handle the stream error at the spawnGogServe pipe owner, matching src/process/exec.ts while leaving exit/restart semantics intact. The foreground Gmail run path uses inherited stdio and is not affected.

AGENTS.md: found and applied where relevant.

Codex review notes: model internal, reasoning high; reviewed against 241c761d0036.

Label changes

Label justifications:

  • P2: The PR fixes a limited Gmail watcher robustness bug that can crash that watcher path without broad compatibility or product impact.
  • rating: 🐚 platinum hermit: Overall readiness is 🐚 platinum hermit; proof is 🦞 diamond lobster and patch quality is 🐚 platinum hermit.
  • status: 👀 ready for maintainer look: ClawSweeper has no concrete contributor-facing blocker left for this PR. Sufficient (live_output): The PR body includes copied live output from a real watcher-path proof using a fake gog binary and real stdout/stderr stream error events, and the current head's Real behavior proof check succeeded.
  • proof: sufficient: Contributor real behavior proof is sufficient. The PR body includes copied live output from a real watcher-path proof using a fake gog binary and real stdout/stderr stream error events, and the current head's Real behavior proof check succeeded.
Evidence reviewed

PR surface:

Source +6, Tests +27, Other +102. Total +135 across 3 files.

View PR surface stats
Area Files Added Removed Net
Source 1 6 0 +6
Tests 1 27 0 +27
Docs 0 0 0 0
Config 0 0 0 0
Generated 0 0 0 0
Other 1 102 0 +102
Total 3 135 0 +135

What I checked:

  • Current main lacks stream error handlers: On current main, spawnGogServe pipes stdout/stderr and attaches data listeners, while only the child process itself has an error listener. (src/hooks/gmail-watcher.ts:75, 241c761d0036)
  • PR head adds the intended handlers: The PR head adds stdout and stderr stream error listeners before the existing data listeners, logging stream failures without changing child exit/restart handling. (src/hooks/gmail-watcher.ts:82, f49f135750ba)
  • Regression coverage: The added test emits stdout and stderr stream errors from mocked child streams and expects startGmailWatcher to resolve successfully. (src/hooks/gmail-watcher.test.ts:366, f49f135750ba)
  • Real behavior proof script: The proof script creates a fake gog, patches child_process.spawn, starts the real watcher path, emits real stream error events, and exits with PASS when startup still resolves. (scripts/proof/gmail-watcher-stream-errors.mts:49, f49f135750ba)
  • Sibling Gmail surface checked: The foreground Gmail runner uses inherited stdio for its gog watch serve process, so it does not share this piped stdout/stderr listener failure mode. (src/hooks/gmail-ops.ts:363, 241c761d0036)
  • Shared process invariant checked: The shared exec helper already treats stdout/stderr pipe errors as independent from child exit/close, supporting this PR's local handler placement. (src/process/exec.ts:617, 241c761d0036)

Likely related people:

  • SebTardif: Merged Gmail watcher re-entry, interval, listener cleanup, and respawn fixes in the same source and test files. (role: recent area contributor; confidence: high; commits: 2ffd7a71722f, 94968c83c6d5, 0a38932ed904; files: src/hooks/gmail-watcher.ts, src/hooks/gmail-watcher.test.ts)
  • samzong: Authored the merged gateway Gmail watcher restart and abort-handling work that substantially touched the watcher path and adjacent tests. (role: gateway watcher contributor; confidence: medium; commits: 2fa853dce5ca; files: src/hooks/gmail-watcher.ts, src/hooks/gmail-watcher.test.ts, src/gateway/server-startup-post-attach.ts)
  • cxbAsDev: Has a merged current-main Gmail watcher/foreground renewal error fix in the same runtime area, beyond this PR. (role: recent adjacent contributor; confidence: medium; commits: b6e4cd6bf4ea; files: src/hooks/gmail-watcher.ts, src/hooks/gmail-ops.ts)
What the crustacean ranks mean
  • 🦀 challenger crab: rare, exceptional readiness with strong proof, clean implementation, and convincing validation.
  • 🦞 diamond lobster: very strong readiness with only minor maintainer review expected.
  • 🐚 platinum hermit: good normal PR, likely mergeable with ordinary maintainer review.
  • 🦐 gold shrimp: useful signal, but proof or patch confidence is still limited.
  • 🦪 silver shellfish: thin signal; proof, validation, or implementation needs work.
  • 🧂 unranked krab: not merge-ready because proof is missing/unusable or there are serious correctness or safety concerns.
  • 🌊 off-meta tidepool: rating does not apply to this item.

Shiny media proof means a screenshot, video, or linked artifact directly shows the changed behavior. Runtime, network, CSP, and security claims still need visible diagnostics.

How this review workflow works
  • ClawSweeper keeps one durable marker-backed review comment per issue or PR.
  • Re-runs edit this comment so the latest verdict, findings, and automation markers stay together instead of adding duplicate bot comments.
  • A fresh review can be triggered by eligible @clawsweeper re-review comments, exact-item GitHub events, scheduled/background review runs, or manual workflow dispatch.
  • PR/issue authors and users with repository write access can comment @clawsweeper re-review or @clawsweeper re-run on an open PR or issue to request a fresh review only.
  • Maintainers can also comment @clawsweeper review to request a fresh review only.
  • Fresh-review commands do not start repair, autofix, rebase, CI repair, or automerge.
  • Maintainer-only repair and merge flows require explicit commands such as @clawsweeper autofix, @clawsweeper automerge, @clawsweeper fix ci, or @clawsweeper address review.
  • Maintainers can comment @clawsweeper explain to ask for more context, or @clawsweeper stop to stop active automation.
Review history (5 earlier review cycles)
  • reviewed 2026-07-06T01:29:57.776Z sha 27051ca :: needs real behavior proof before merge. :: none
  • reviewed 2026-07-06T02:16:53.272Z sha bcef18d :: needs real behavior proof before merge. :: none
  • reviewed 2026-07-06T03:55:37.381Z sha bcef18d :: needs real behavior proof before merge. :: none
  • reviewed 2026-07-06T05:25:25.474Z sha 87b0201 :: needs changes before merge. :: [P2] Narrow the spawned command before stringifying
  • reviewed 2026-07-06T05:40:43.791Z sha f1f53f2 :: needs maintainer review before merge. :: none

@clawsweeper clawsweeper Bot added rating: 🦪 silver shellfish Thin PR readiness signal; proof, validation, or implementation needs work. status: 📣 needs proof The PR needs real behavior proof before ClawSweeper can clear the contributor ask. P2 Normal backlog priority with limited blast radius. labels Jul 6, 2026
@openclaw-barnacle openclaw-barnacle Bot added scripts Repository scripts size: S and removed size: XS labels Jul 6, 2026
@cxbAsDev

cxbAsDev commented Jul 6, 2026

Copy link
Copy Markdown
Contributor Author

@clawsweeper re-review

Added a real behavior proof script per the review feedback:

  • scripts/proof/gmail-watcher-stream-errors.mts runs the focused regression suite (src/hooks/gmail-watcher.test.ts) and reports PASS/FAIL.
  • Verified locally: 9 tests pass and the proof script reports PASS.
  • PR body updated with the proof command and output.

@clawsweeper

clawsweeper Bot commented Jul 6, 2026

Copy link
Copy Markdown
Contributor

🦞🧹
ClawSweeper re-review requested.

I asked ClawSweeper to review this item again.
Action: item re-review queued (workflow sweep.yml, event repository_dispatch).
Result: the existing ClawSweeper review comment will be edited in place when the review finishes.

@cxbAsDev

cxbAsDev commented Jul 6, 2026

Copy link
Copy Markdown
Contributor Author

@clawsweeper re-review

All CI checks are now green:

  • check-lint
  • Real behavior proof

Proof script and regression tests are included in the PR body. Ready for another look.

@cxbAsDev

cxbAsDev commented Jul 6, 2026

Copy link
Copy Markdown
Contributor Author

@clawsweeper re-review

Replaced the proof scripts with real behavior proofs that exercise actual production code paths and emit real stream error events (or trigger a real EISDIR filesystem error for transcripts). All proofs pass locally; PR bodies are updated with commands and output.

@clawsweeper

clawsweeper Bot commented Jul 6, 2026

Copy link
Copy Markdown
Contributor

🦞🧹
ClawSweeper re-review requested.

I asked ClawSweeper to review this item again.
Action: item re-review queued (workflow sweep.yml, event repository_dispatch).
Result: the existing ClawSweeper review comment will be edited in place when the review finishes.

@cxbAsDev
cxbAsDev force-pushed the fix/gmail-watcher-stream-errors branch from 3f23e71 to a309b46 Compare July 6, 2026 05:13
@cxbAsDev
cxbAsDev force-pushed the fix/gmail-watcher-stream-errors branch from 2181688 to 87b0201 Compare July 6, 2026 05:17
@clawsweeper clawsweeper Bot added proof: sufficient ClawSweeper judged the real behavior proof convincing. rating: 🦐 gold shrimp Decent PR readiness signal, but merge confidence is limited. status: ⏳ waiting on author ClawSweeper has contributor-facing work open and is waiting for author action. and removed rating: 🦪 silver shellfish Thin PR readiness signal; proof, validation, or implementation needs work. status: 📣 needs proof The PR needs real behavior proof before ClawSweeper can clear the contributor ask. labels Jul 6, 2026
@cxbAsDev
cxbAsDev force-pushed the fix/gmail-watcher-stream-errors branch 2 times, most recently from 1270ffa to f1f53f2 Compare July 6, 2026 05:35
@clawsweeper clawsweeper Bot added rating: 🐚 platinum hermit Good normal PR readiness with ordinary maintainer review expected. status: 👀 ready for maintainer look ClawSweeper has no concrete contributor-facing blocker left for this PR. and removed rating: 🦐 gold shrimp Decent PR readiness signal, but merge confidence is limited. status: ⏳ waiting on author ClawSweeper has contributor-facing work open and is waiting for author action. labels Jul 6, 2026
@cxbAsDev
cxbAsDev force-pushed the fix/gmail-watcher-stream-errors branch from f1f53f2 to f49f135 Compare July 6, 2026 05:52
@vincentkoc

Copy link
Copy Markdown
Member

No description provided.

@vincentkoc vincentkoc self-assigned this Jul 6, 2026
@openclaw-clownfish
openclaw-clownfish Bot merged commit e66f43e into openclaw:main Jul 6, 2026
96 checks passed
vincentkoc added a commit to zhangqueping/openclaw that referenced this pull request Jul 6, 2026
* origin/main: (1287 commits)
  fix(android): block loopback canvas navigation (openclaw#99874)
  fix(hooks): suppress unhandled stdout/stderr stream errors in gmail watcher (openclaw#100519)
  fix(memory-core): guard qmd mcporter JSON.parse against non-JSON stdout (openclaw#98381)
  fix(build): fall back to tsx for build TypeScript scripts (openclaw#91262)
  feat(skills): suggest saving detected reusable workflows by default (openclaw#95477) (openclaw#100692)
  docs(changelog): remove generated release-note entries
  feat(telegram): offer BotFather web app flow in setup help and docs (openclaw#100540)
  fix(ios): unify Talk and Settings row typography on one branded detail row (openclaw#100515)
  feat(gateway): add persisted crash-loop breaker and fatal-config exit contract
  refactor(macos): lock and unify PortGuardian tunnel record persistence so concurrent app instances cannot lose orphan records (openclaw#100601)
  fix: stop reconnecting on protocol mismatch (openclaw#98414)
  fix(maint): reuse recent hosted gates after rebase (openclaw#100663)
  fix(ui): reopen web terminals without stale content (openclaw#100665)
  fix(browser): diagnose empty WSL2 Chrome replies (openclaw#100590)
  fix(ios): chat snaps back to bottom when scrolling to top via status-bar tap (openclaw#100502)
  Treat already-compacted CLI compaction as no-op (openclaw#99136)
  docs(changelog): remove direct main fix entry
  fix(feishu): strip internal tool-trace banners from outbound text (openclaw#98705)
  fix(message): thread --limit through to CLI formatter and surface provider pagination hints (openclaw#99089)
  fix(voyage): close response body stream when batch output JSONL parsing throws (openclaw#98840)
  ...

# Conflicts:
#	extensions/memory-wiki/package.json
github-actions Bot pushed a commit to Desicool/openclaw that referenced this pull request Jul 6, 2026
…atcher (openclaw#100519)

* fix(hooks): suppress unhandled stdout/stderr stream errors in gmail watcher

* proof(gmail-watcher): add real behavior proof script for stream error catch

* proof(gmail-watcher): replace wrapper with real stream error proof

* style: apply oxfmt to changed files
giodl73-repo pushed a commit to giodl73-repo/openclaw that referenced this pull request Jul 8, 2026
…atcher (openclaw#100519)

* fix(hooks): suppress unhandled stdout/stderr stream errors in gmail watcher

* proof(gmail-watcher): add real behavior proof script for stream error catch

* proof(gmail-watcher): replace wrapper with real stream error proof

* style: apply oxfmt to changed files
@cxbAsDev
cxbAsDev deleted the fix/gmail-watcher-stream-errors branch July 15, 2026 03:32
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

P2 Normal backlog priority with limited blast radius. proof: sufficient ClawSweeper judged the real behavior proof convincing. rating: 🐚 platinum hermit Good normal PR readiness with ordinary maintainer review expected. scripts Repository scripts size: S status: 👀 ready for maintainer look ClawSweeper has no concrete contributor-facing blocker left for this PR.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants