fix(oauth): listen for openExternal spawn errors on darwin and win32 - #341
Conversation
Node emits ChildProcess error asynchronously when spawn fails (ENOENT, EACCES). The Linux xdg-open path already swallowed that event. The darwin open and win32 rundll32 paths called unref() without a listener, so a missing helper terminated mcporter mid-OAuth. Attach the same no-op error listener before unref() on all platforms. Signed-off-by: Sebastien Tardif <sebtardif@ncf.ca>
|
🦞👀 Pull request received. I will update this pull request when review starts. |
|
Codex review: needs maintainer review before merge. Reviewed September 4, 2026, 5:04 AM ET / 09:04 UTC. ClawSweeper reviewWhat this changesThe PR handles asynchronous browser-launch errors on macOS and Windows so OAuth can continue through the printed authorization URL, with regression tests and documentation. Merge readiness✅ Ready for maintainer review Keep open for landing: current main and v0.13.8 still contain the defect. The focused patch has convincing recorded behavior proof and no actionable correctness findings. Priority: P2 Review scores
Verification
How this fits togetherMCPorter's OAuth provider launches a browser for authorization and waits for a local HTTP callback. Browser-launch failures must leave that callback listener available so users can finish authorization manually. flowchart TD
A[OAuth authorization request] --> B[Launch system browser]
B --> C{Browser helper starts?}
C -->|Yes| D[Browser authorization]
C -->|No| E[Open printed URL manually]
E --> D
D --> F[Local HTTP callback]
F --> G[Continue OAuth]
Before mergeNone. Agent review detailsSecurityNone. Review metrics
Technical reviewBest possible solution: Preserve best-effort browser launching across platforms while keeping the existing manual authorization flow available after helper failures. Do we have a high-confidence way to reproduce the issue? Yes: current-main source exposes unhandled asynchronous spawn errors when open or rundll32 cannot start, and the supplied before/after runs report that exact failure. This read-only review did not execute the reproduction. Is this the best way to solve the issue? Yes: matching Linux's existing error handling is the smallest repair; --no-browser is a deliberate opt-out and does not protect ordinary browser-launch attempts from unexpected failures. AGENTS.md: found and applied where relevant. Codex review notes: model internal, reasoning high; reviewed against ab0c27f03fd7. LabelsLabel justifications:
EvidenceWhat I checked:
Likely related people:
Rating scale
Overall follows the weaker of proof and patch quality. Workflow
HistoryReview history (8 earlier review cycles)
|
Replace simulated late-error process handlers with real subprocess regressions, document the manual authorization path, and retain the contributor fix. Co-authored-by: Sebastien Tardif <sebtardif@ncf.ca>
Preserve the reviewed browser-spawn fix while incorporating the dependency refresh from openclaw#343. Co-authored-by: Sebastien Tardif <sebtardif@ncf.ca>
Preserve the reviewed environment fix and both Unreleased entries while incorporating openclaw#343 and openclaw#341. Co-authored-by: JUSHUANGHUI LI <oodadoudou@gmail.com>
A failed macOS
openor Windowsrundll32spawn can emit an asynchronous child-process error afteropenExternalreturns. Without an error listener, Node terminates OAuth even though mcporter prints a manual authorization URL. Attach the same listener already used for Linux so the existing manual flow remains usable; browser arguments, shell-free Windows launching, and--no-browserbehavior are unchanged.Thanks @SebTardif for the fix. The maintainer follow-up replaces simulated late-error/global-process handlers with regressions in real Node subprocesses, documents the manual fallback, and adds contributor credit to the changelog.
On Node 24.20.0 / pnpm 10.34.5,
pnpm checkandpnpm testpass: 1,796 tests passed, 26 skipped. Independent built-runtime proof compares the original baselineab0c27f03fd7d27aa5b48774ac749a4548836234with this candidate:openis missing. The fixed provider retains the printed manual URL, accepts a real HTTP request to its localhost callback, and returns the synthetic authorization code. Its callback server is then closed.Only synthetic data and local processes were used. The Windows branch was exercised on macOS here; cross-platform CI runs the maintained process regressions natively. This does not claim a complete Windows browser/authorization-server session.
Full-candidate isolated Codex review (original patch plus maintainer changes) found no actionable P0–P2 issues. The contributor's original commit is preserved; the maintainer follow-up carries a co-author trailer.
The existing contributor branch was reconciled with main after #343 by a normal merge commit, preserving all contributor history. Frozen install/build, all nine focused OAuth regressions, real missing-executable checks, and the native macOS provider callback proof pass again with the updated dependencies. Full combined P0–P2 reviews before the integration commit and landing found no actionable issues.
Final head:
e0ceb538c047e7b0ab2596f8e77a19af1bbbe2b2; base:e212368533bc0bdd94b5a3c89866fd912431d83c. CI passed on Ubuntu, macOS 15, and Windows, including the full suites and real-process regressions. No CI retries were needed.