Hacktoberfest 2026: the issues maintainers tagged for October, open and beginner-friendly. Browse Hacktoberfest issues

setup-learning.ts fails on Windows with "spawn npx.cmd EINVAL"

Open Beginner friendly
#792 0 comments 0 reactions 0 assignees View on GitHub

Maintainers usually reply within 1 day

@Caldas is already working on this.

Since Oct 14, 2026.

  • #793 by @Caldas — open

Assessment

Difficulty
2/5
Estimated time
1-3 hours
Newbie friendliness
80/100
Issue type
Bug
Clarity
Clearly specified
Activity status
Active
Tech stack
nodejs, typescript
Domain
backend, cli

Research direction

Start with runCli in server/src/learning/ensure-container.ts (around lines 124-149), where spawn is called without shell on Windows, and trace the entry from scripts/setup-learning.ts. Reproduce on Windows with bun scripts/setup-learning.ts to see the EINVAL, and check that the child.on("error") handler is bypassed. Done when the setup script runs on Windows and the CLI commands succeed, with macOS and Linux behaviour unchanged.

Written by the indexing model from the issue text.

Description

On Windows, bun scripts/setup-learning.ts (Quick start, step 2) stops before doing anything, and prints only this:

PS C:\...\openbot> bun scripts/setup-learning.ts
spawn npx.cmd EINVAL

npx --yes copilotkit@latest login and project select had both succeeded beforehand, from the OpenBot root. Nothing is written to .env, so neither the runtime key nor the openbot Learning container is set up.

Cause

runCli in server/src/learning/ensure-container.ts:124-149 starts the CopilotKit CLI like this:

const child = spawn(
  process.platform === "win32" ? "npx.cmd" : "npx",
  ["--yes", "copilotkit@latest", ...args],
  { cwd: directory, env: cliEnvironment(), stdio: ["ignore", "pipe", "pipe"] },
);

Since the fix for CVE-2024-27980, Node refuses to spawn a .cmd or .bat file without shell: true, and Bun does the same. The refusal is a synchronous EINVAL thrown by spawn() itself, not an 'error' event. As a result, the child.on("error", () => finish(127)) handler at line 147 never runs. The throw happens inside the Promise executor, so it becomes a rejection, and setup-learning.ts exits with the bare message.

Minimal reproduction, Bun 1.4.3 on Windows 11:

import { spawn } from "node:child_process";
spawn("npx.cmd", ["--version"]);                 // throws: spawn npx.cmd EINVAL
spawn("npx.cmd", ["--version"], { shell: true }); // runs, prints 11.19.0

The server calls the same runCli from ensureLearningContainer at boot (server/src/index.ts:360) when a CLI login is present. Automatic container creation should therefore fail the same way on Windows, although I have only reproduced it through the setup helper.

Suggested fix

Run through the shell on Windows only:

{
  cwd: directory,
  env: cliEnvironment(),
  shell: process.platform === "win32",
  stdio: ["ignore", "pipe", "pipe"],
}

With shell: true the arguments are joined into a cmd.exe command line rather than passed as an argv. That is safe here because every caller passes literals (whoami, project list --json). cliEnvironment() already keeps COMSPEC, SystemRoot and PATHEXT, so cmd.exe resolves. macOS and Linux are unchanged.

Windows 11 Enterprise 10.0.26200, Bun 1.4.3, Node 24.21.0 / npm 11.19.0, OpenBot at 8c9ad4c. Related: #679 and #681 (other Windows checkout problems).

Dominant language
TypeScript
Stars
6.6k
Forks
914
Avg merge
19h 22m
Merged PRs (30d)
140

Getting set up

  • Ships a Dockerfile or Docker Compose file
  • Has a pull request template
  • No contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

More from CopilotKit/OpenBot

All issues in CopilotKit/OpenBot

Similar issues

More TypeScript issues

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.