Skip to content

fix(watch-pr): report a gh that cannot start as a status-query blocker - #820

Open
rudycelekli wants to merge 1 commit into
cursor:mainfrom
rudycelekli:fix/watch-pr-gh-spawn-error-20261023
Open

rudycelekli wants to merge 1 commit into
cursor:mainfrom
rudycelekli:fix/watch-pr-gh-spawn-error-20261023

Conversation

@rudycelekli

@rudycelekli rudycelekli commented Oct 24, 2026 •

Copy link
Copy Markdown
Contributor

When the watcher cannot start gh at all, for example because it is not on PATH or the spawn fails with a system error, the spawn error escapes run() as a raw rejection. Nothing above it converts that into a WatcherQueryError, so the CLI dies with an uncaught stack trace and never prints a JSON verdict. Callers that expect the documented status-query BLOCKER (exit 7, "verify current PR context, GitHub authentication, and API availability") get a crash instead. Under Bun the error is thrown synchronously from spawn; under Node it arrives as an error event, and neither path was handled.

run() now treats a command that cannot start the same as one that exits nonzero: it resolves with code -1 and the spawn error as stderr. The existing runJson path then raises a command-exit query failure, so the error goes through the normal retry budget and ends as a status-query BLOCKER whose detail names the problem (for example Executable not found in $PATH: "gh"). Callers that already check code !== 0, such as the origin and checks fast paths, fall back as they do for any other failed command.

Validation: added a github.test.ts case that runs GhGitHubReader.pullRequest in a subprocess with a PATH that has no gh. On main it receives the raw "Executable not found" error; with the fix it receives a command-exit WatcherQueryError. Running the CLI by hand with --status-only and no gh on PATH now prints the BLOCKER JSON and exits 7 instead of a stack trace. Ran bun test watch-pr check-plan.test.ts (62 pass), bun run typecheck, node scripts/validate-plugins.mjs, node scripts/generate-pstack-harness-trees.mjs --check, node --test pstack/skills/*/scripts/test/*.test.mjs (57 pass), and git diff --check.


Note

Low Risk
Narrow change to subprocess error handling in the GitHub CLI wrapper; improves fail-closed behavior without altering successful gh paths.

Overview
When gh cannot be started (missing from PATH, spawn failure), the watch-pr GitHub helper no longer lets that error bubble out as an uncaught rejection.

run() now treats “command failed to start” like a nonzero exit: it resolves with code: -1 and the error text in stderr, covering Bun’s synchronous spawn throw and Node’s error event. runJson then raises the existing command-exit WatcherQueryError, so the CLI can surface the usual status-query BLOCKER (exit 7) instead of crashing.

A subprocess test runs GhGitHubReader.pullRequest with a PATH that has no gh and expects command-exit rather than a raw executable-not-found string.

Reviewed by Cursor Bugbot for commit d37cde9. Bugbot is set up for automated code reviews on this repo. Configure here.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant