Before submitting your bug report
Relevant environment info
CI/CD issue — `CLI PR Checks` / `test (windows-latest, *)`
extensions/cli, vitest, windows-latest GitHub runner
Description
src/tools/runTerminalCommand.test.ts > runTerminalCommandTool > basic error handling > should handle non-existent commands hangs until vitest's 30s timeout
on windows-latest, failing the test job. It is the only failure in the run —
1 failed | 1671 passed | 49 skipped.
Notably, every other test in the same file passes on the same runner, including
ones that spawn PowerShell successfully:
❯ src/tools/runTerminalCommand.test.ts (8 tests | 1 failed) 34086ms
✓ basic platform-specific terminal execution > should execute a simple echo command 460ms
✓ basic platform-specific terminal execution > should get current directory 661ms
✓ basic platform-specific terminal execution > should list directory contents 427ms
✓ basic platform-specific terminal execution > should handle command that produces version info 391ms
× basic error handling > should handle non-existent commands 30014ms
→ Test timed out in 30000ms.
✓ platform-specific features > should work with Windows commands 2130ms
✓ WSL detection > should cache the WSL detection result 0ms
✓ WSL detection > should return false on non-Linux platforms 0ms
So PowerShell spawns fine; it's specifically the non-existent command path
that never settles. The test runs:
const command = "definitely-not-a-real-command-xyz123";
await expect(runTerminalCommandTool.run({ command })).rejects.toMatch(
/Error \(exit code|Command timed out|not found|not recognized/,
);
which on Windows becomes:
powershell.exe -NoLogo -ExecutionPolicy Bypass -Command definitely-not-a-real-command-xyz123
The promise rejects from child.on("close") only when code !== 0 && stderr is
truthy. If PowerShell's CommandNotFoundException output doesn't reach the
stderr handler before close, that condition is false and nothing rejects or
resolves — the promise just hangs. That would be consistent with the existing
note in .github/workflows/cli-pr-checks.yml:
# e2e tests are failing on Windows specifically - likely due to stdout flush issues
I want to be clear that I haven't proven that mechanism — I can't reproduce it
locally and the CI logs don't show which branch it's stuck in. But two things
independently look wrong regardless of the root cause:
1. The test's own timeout branch is unreachable. runTerminalCommand.ts
defaults to TIMEOUT_MS = 180000, overridden only when NODE_ENV === "test" && process.env.TEST_TERMINAL_TIMEOUT is set. TEST_TERMINAL_TIMEOUT isn't set
anywhere in the repo (it appears in exactly one file — its own read), and
cli-pr-checks.yml just runs npm test. With vitest.config.ts setting
testTimeout: 30000, the tool's 180s timeout can never fire first, so the
/Command timed out/ alternative in the test's regex is dead and any hang
surfaces as a bare vitest timeout with no diagnostics.
2. The rejection condition is stricter than the assertion. The test accepts
not found / not recognized, but the implementation only rejects when there is
both a non-zero exit code and non-empty stderr. A shell that reports command
-not-found with an empty stderr (or flushes late) silently produces neither a
resolve nor a reject.
Possible mitigations, in case they're useful: pass -NoProfile to the Windows
PowerShell invocation, set TEST_TERMINAL_TIMEOUT below testTimeout in the
CLI test env so the tool's own timeout path is exercised, and/or reject on
close when code !== 0 regardless of whether stderr is empty.
To reproduce
Push any PR that triggers CLI PR Checks. It does not reproduce on every
Windows leg — on my PR (#13159, which touches only core/llm/* and docs) it hit:
- run
33738790065 → test (windows-latest, 24)
- run
34791213602 → test (windows-latest, 22)
Same test, same 30s timeout, different Node leg each time, while the other
Windows legs in the same matrix passed. Other recent PRs' CLI checks are green,
so it isn't failing universally the way #13164 is.
Log output
FAIL src/tools/runTerminalCommand.test.ts > runTerminalCommandTool > basic error handling > should handle non-existent commands
Error: Test timed out in 30000ms.
If this is a long-running test, pass a timeout value as the last argument or configure it globally with "testTimeout".
Test Files 1 failed | 154 passed | 5 skipped (160)
Tests 1 failed | 1671 passed | 49 skipped (1721)
##[error]Error: Test timed out in 30000ms.
##[error]Process completed with exit code 1.
Before submitting your bug report
Relevant environment info
Description
src/tools/runTerminalCommand.test.ts > runTerminalCommandTool > basic error handling > should handle non-existent commandshangs until vitest's 30s timeouton
windows-latest, failing thetestjob. It is the only failure in the run —1 failed | 1671 passed | 49 skipped.
Notably, every other test in the same file passes on the same runner, including
ones that spawn PowerShell successfully:
So PowerShell spawns fine; it's specifically the non-existent command path
that never settles. The test runs:
which on Windows becomes:
The promise rejects from
child.on("close")only whencode !== 0 && stderristruthy. If PowerShell's
CommandNotFoundExceptionoutput doesn't reach thestderrhandler beforeclose, that condition is false and nothing rejects orresolves — the promise just hangs. That would be consistent with the existing
note in
.github/workflows/cli-pr-checks.yml:# e2e tests are failing on Windows specifically - likely due to stdout flush issuesI want to be clear that I haven't proven that mechanism — I can't reproduce it
locally and the CI logs don't show which branch it's stuck in. But two things
independently look wrong regardless of the root cause:
1. The test's own timeout branch is unreachable.
runTerminalCommand.tsdefaults to
TIMEOUT_MS = 180000, overridden only whenNODE_ENV === "test" && process.env.TEST_TERMINAL_TIMEOUTis set.TEST_TERMINAL_TIMEOUTisn't setanywhere in the repo (it appears in exactly one file — its own read), and
cli-pr-checks.ymljust runsnpm test. Withvitest.config.tssettingtestTimeout: 30000, the tool's 180s timeout can never fire first, so the/Command timed out/alternative in the test's regex is dead and any hangsurfaces as a bare vitest timeout with no diagnostics.
2. The rejection condition is stricter than the assertion. The test accepts
not found/not recognized, but the implementation only rejects when there isboth a non-zero exit code and non-empty stderr. A shell that reports command
-not-found with an empty stderr (or flushes late) silently produces neither a
resolve nor a reject.
Possible mitigations, in case they're useful: pass
-NoProfileto the WindowsPowerShell invocation, set
TEST_TERMINAL_TIMEOUTbelowtestTimeoutin theCLI test env so the tool's own timeout path is exercised, and/or reject on
closewhencode !== 0regardless of whether stderr is empty.To reproduce
Push any PR that triggers
CLI PR Checks. It does not reproduce on everyWindows leg — on my PR (#13159, which touches only
core/llm/*and docs) it hit:33738790065→test (windows-latest, 24)34791213602→test (windows-latest, 22)Same test, same 30s timeout, different Node leg each time, while the other
Windows legs in the same matrix passed. Other recent PRs' CLI checks are green,
so it isn't failing universally the way #13164 is.
Log output