JuliusBrussee/caveman · error
cannot safely launch non-Node Windows command shim: ${execut
Error message
cannot safely launch non-Node Windows command shim: ${executable} What it means
Thrown by portableProcessInvocation() on win32 when the .cmd/.bat shim was read successfully but parseWindowsNodeShim() cannot extract a relative script path from it. The function only launches shims it can prove are standard Node/npm wrappers (which reference a node script with %~dp0-relative logic); anything else — a plain batch file, a custom launcher, a shell script named .cmd — is rejected rather than executed, because executing arbitrary batch content indirectly is unsafe.
Source
Thrown at packages/subagent-tax/lib/process-tree.mjs:53
return null;
}
export function portableProcessInvocation(
command,
args,
{ platform = process.platform, env = process.env, execPath = process.execPath } = {},
) {
if (platform !== "win32") return { command, args: [...args] };
const executable = resolveWindowsCommand(command, env);
if (!executable) throw Object.assign(new Error(`command not found: ${command}`), { code: "ENOENT" });
if (!/\.(?:cmd|bat)$/i.test(executable)) return { command: executable, args: [...args] };
const stat = statSync(executable);
if (!stat.isFile() || stat.size > 256 * 1024) {
throw new Error(`cannot safely launch Windows command shim: ${executable}`);
}
const relativeScript = parseWindowsNodeShim(readFileSync(executable, "utf8"));
if (!relativeScript) {
throw new Error(`cannot safely launch non-Node Windows command shim: ${executable}`);
}
const script = resolve(dirname(executable), ...relativeScript.split(/[\\/]+/));
if (!statSync(script).isFile()) throw new Error(`Windows command shim target is missing: ${script}`);
return { command: execPath, args: [script, ...args] };
}
export function harnessSpawnOptions(platform = process.platform) {
return {
detached: platform !== "win32",
windowsHide: true,
};
}
export function forceKillTree(
child,
{
platform = process.platform,
kill = process.kill,View on GitHub (pinned to 27d5a3981a)
Solutions
- Bypass the shim: pass the absolute path to the underlying executable or Node script as command (Node scripts can be launched as [execPath, script, ...args] yourself).
- If the tool is npm-distributed, reinstall it with npm so a standard npm .cmd shim is generated.
- If you maintain the shim, rewrite it as a standard npm-style Node wrapper so parseWindowsNodeShim can extract the script target.
Example fix
// before
const inv = portableProcessInvocation("pnpm", ["run", "build"], { platform: "win32" }); // non-npm shim -> throws
// after
const inv = { command: process.execPath,
args: ["C:/proj/node_modules/pnpm/bin/pnpm.cjs", "run", "build"] }; Defensive patterns
Strategy: fallback
Validate before calling
import { readFileSync } from "node:fs";
function looksLikeNodeShim(executable) {
const text = readFileSync(executable, "utf8");
return /node(\.exe)?"? "%~dp0/i.test(text) || /node_modules/.test(text);
} Try / catch
try {
const inv = portableProcessInvocation(cmd, args, { platform: "win32" });
} catch (err) {
if (/non-Node Windows command shim/.test(err.message)) {
// fallback: launch underlying exe or [execPath, script] directly
} else throw err;
} Prevention
- Install CLIs via npm so standard shims are generated.
- When wrapping tools yourself, write npm-style Node shims or expose the raw binary.
When it happens
Trigger: Calling portableProcessInvocation with platform win32 where the resolved command is a hand-written .cmd/.bat (e.g. "@echo off\nmyapp.exe %*") or a shim in a format the parser does not recognize (yarn/pnpm/pnpm-style or volta shims whose internals differ from npm's node.exe invocation pattern).
Common situations: A user installed the CLI through a non-npm package manager whose shim format differs; a project checked in a custom .cmd wrapper; the shim format changed with a newer npm/pnpm/bun release.
Related errors
- cannot safely launch Windows command shim: ${executable}
- cannot safely launch non-Node Windows command shim: ${execut
- unsafe Windows command shim: ${executable}
- non-Node Windows command shim: ${executable}
- Windows command shim target is missing: ${script}
AI-assisted analysis of JuliusBrussee/caveman@27d5a3981a (2026-08-15).
Data as JSON: /api/errors/3547a6aa2a8a49f9.
Report an issue: GitHub.