From bbd8a1a947ba26c0e59f98819cab9e20898ff0b7 Mon Sep 17 00:00:00 2001 From: ForgottenR <454906468@qq.com> Date: Wed, 24 Jun 2026 15:27:00 +0800 Subject: [PATCH] fix(cli): resolve spawn EFTYPE on Windows for kimi web and /web (#903) * fix(cli): resolve spawn EFTYPE on Windows for kimi web and /web * chore(changeset): clarify affected Windows installation methods --------- Co-authored-by: qer Co-authored-by: liruifengv --- .changeset/fix-web-daemon-spawn-windows.md | 5 +++++ apps/kimi-code/src/cli/sub/server/daemon.ts | 9 ++++++++- 2 files changed, 13 insertions(+), 1 deletion(-) create mode 100644 .changeset/fix-web-daemon-spawn-windows.md diff --git a/.changeset/fix-web-daemon-spawn-windows.md b/.changeset/fix-web-daemon-spawn-windows.md new file mode 100644 index 000000000..9a2a11184 --- /dev/null +++ b/.changeset/fix-web-daemon-spawn-windows.md @@ -0,0 +1,5 @@ +--- +"@moonshot-ai/kimi-code": patch +--- + +Fix `kimi web` and `/web` failing to start the background server daemon on Windows with `spawn EFTYPE` when the CLI is installed via npm/pnpm or run from source. The official single-binary install script was not affected. diff --git a/apps/kimi-code/src/cli/sub/server/daemon.ts b/apps/kimi-code/src/cli/sub/server/daemon.ts index 1c840d418..f8ef8ffa8 100644 --- a/apps/kimi-code/src/cli/sub/server/daemon.ts +++ b/apps/kimi-code/src/cli/sub/server/daemon.ts @@ -204,9 +204,16 @@ export function spawnDaemonChild(options: SpawnDaemonChildOptions): void { if (options.idleGraceMs !== undefined) { args.push('--idle-grace-ms', String(options.idleGraceMs)); } + // On Windows `.mjs` files are not executable PE binaries, so we must run + // the script through the Node binary rather than spawning it directly. In + // SEA mode or when re-spawning from an already-running daemon, `program` is + // `process.execPath` itself, so no script argument is needed. + const execPath = process.execPath; + const spawnArgs = program === execPath ? args : [program, ...args]; + const logFd = openSync(logPath, 'a'); try { - const child = spawn(program, args, { + const child = spawn(execPath, spawnArgs, { detached: true, // Run from the server log directory instead of inheriting the caller's // cwd, so the long-lived daemon does not pin the directory it was