Skip to content

CLI: runTerminalCommand "should handle non-existent commands" intermittently hangs to vitest's 30s timeout on windows-latest #13273

Description

@djrok212

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 33738790065test (windows-latest, 24)
  • run 34791213602test (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.

Activity

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions