Skip to content

fix(server): skip cmd.exe for multi-line args on Windows - #4428

Closed
eden881 wants to merge 1 commit into
getpaseo:mainfrom
eden881:fix/windows-multiline-argument-truncation
Closed

fix(server): skip cmd.exe for multi-line args on Windows#4428
eden881 wants to merge 1 commit into
getpaseo:mainfrom
eden881:fix/windows-multiline-argument-truncation

Conversation

@eden881

@eden881 eden881 commented Sep 7, 2026

Copy link
Copy Markdown

Type of change

  • Bug fix
  • New feature
  • Enhancement
  • Refactor
  • Docs

Reasoning

On Windows every gh api graphql call the daemon makes fails, so anything backed by GraphQL is quietly missing from the changes pane - merge state, auto merge facts, PR timeline and comments, and the batched PR status poll.
Nothing surfaces in the UI because loadPullRequestGithubFacts catches GitHubCommandError and returns null, so the pane just renders less than it should and you have no idea why.

I found this on my own machine after a separate gh problem sent me into C:\Users\<USER>\.paseo\daemon.log, which was full of:

GitHub CLI command failed: gh api graphql -f query=query PaseoBatchPullRequestStatus {...}
stderr: gh: Expected NAME, actual: (none) ("") at [1, 35]

Column 35 is the end of query PaseoBatchPullRequestStatus {, so GitHub only ever received the first line of the query.

Timeline is basically:

  1. createForgeCliRunner calls execCommand("gh", ...) with the bare binary name
  2. shouldUseWindowsShell returns true on win32 for a command with no path separator and no extension, so the spawn goes through cmd.exe /d /s /c
  3. cmd.exe can't carry a line break inside an argument. It drops everything after a \n and silently swallows a lone \r. quoteWindowsArgument handles & | ^ < > ( ) ! but has nothing for line breaks
  4. gh gets a one-line query, GitHub's parser hits EOF where it wants a field, and the whole poll fails

Single line calls like gh pr view --json ... are fine which is what makes this hard to spot - PR status half works, so it shows as flaky instead of broken.

The bare name shell routing only exists so PATHEXT resolution finds gh.exe. libuv does that itself, so skipping the shell when an argument spans lines costs nothing.

Goals

  • gh api graphql reaches the CLI intact on Windows, and the same for the glab / tea runners that share createForgeCliRunner
  • Batch PR status polling, merge and auto merge facts, and PR timeline and comments work on Windows again
  • No behavior change on macOS or Linux

Non-goals

  • Not changing how .cmd or .bat launch - they can't run without the shell, so they keep it, and a multi line argument to one of those stays unsupported
  • Not overriding an explicit shell: from a caller
  • Not touching runGitCommand, as it already passes shell: false, so it was never affected. I checked because I assumed multi line commit messages were broken too and they aren't
  • Not resolving forge binaries to absolute paths. That fixes the same symptom for gh / glab / tea only and leaves the trap in place for whoever passes a multiline argument next

QA

IN PROGRESS
I'll undraft the PR when this section is ready 🙂

Checklist

  • One focused change
  • npm run typecheck passes
  • npm run lint passes
  • npm run format passes
  • QA evidence
  • Tests added or updated where it made sense

@boudra

boudra commented Sep 8, 2026

Copy link
Copy Markdown
Collaborator

Closing for now: this needs Windows before/after output showing that the child receives multiline arguments intact through both execCommand and spawnProcess. Please reopen with that evidence.

@boudra boudra closed this Sep 8, 2026
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.

2 participants