JuliusBrussee/caveman · error · Error
cannot safely launch non-Node Windows command shim
Error message
cannot safely launch non-Node Windows command shim: ${executable} What it means
When a Windows .cmd/.bat shim passes the size/file checks, the library parses it with parseWindowsNodeShim() to extract the relative Node script it delegates to. If the shim's contents do not match the expected Node-shim pattern (no relative script found), the library refuses to launch it, since it would otherwise have to execute an opaque batch file. The message includes the shim path.
Solutions
- Run the tool directly instead of via its shim: invoke node with the real entry script, or the tool's native executable.
- Check what the shim contains (open the reported path) — if it is not a Node shim, it is out of scope for this launcher.
- Regenerate standard npm shims (npm install / npm rebuild) if a package manager rewrote them.
- Wrap the call in a small .js entry point or use a cross-platform JS CLI equivalent of the batch tool.
Example fix
// before
spawn("deploy.cmd", ["--prod"]); // non-Node batch shim, throws
// after
spawn("powershell.exe", ["-File", "deploy.ps1", "--prod"]); Defensive patterns
Strategy: fallback
Validate before calling
import { readFileSync } from "node:fs";
function isNodeShim(executable) {
if (!/\.(?:cmd|bat)$/i.test(executable)) return true;
try { return Boolean(readFileSync(executable, "utf8").match(/node/i) && /%~dp0|"%~dp0"/.test(readFileSync(executable, "utf8"))); }
catch { return false; }
} Try / catch
try {
child = portableProcessInvocation(command, args, env, process.platform);
} catch (e) {
if (e.message.includes("non-Node Windows command shim")) {
// run the tool natively instead of through its batch wrapper
child = spawnNativeAlternative(command, args);
} else throw e;
} Prevention
- Only route Node-tool commands (npm/npx-installed CLIs) through this launcher; call non-Node batch tools natively.
- Avoid custom wrapper .bat/.cmd files for tools this library will spawn.
- Pin package manager (npm vs pnpm) so shim formats stay consistent.
When it happens
Trigger: portableProcessInvocation() on win32 resolving a .cmd/.bat executable whose readFileSync content is not a standard node "...%~dp0...\script.js" style shim — e.g. a hand-written batch wrapper, a shim for a non-Node tool (robocopy.cmd, a custom deploy.bat), or a shim rewritten by another tool manager.
Common situations: Trying to spawn a non-Node .cmd utility through this library; pnpm/yarn re-generated shims in a different format; a corporate wrapper .bat around a tool; antivirus or a provisioning script replacing stock npm shims.
Understand the failure class
Background: UnsupportedOperationException and "is not supported" errors: when a library deliberately refuses a call — this error's family across 30 libraries.
Related errors
- cannot safely launch non-Node Windows command shim
- cannot safely launch non-Node Windows command shim
- cannot safely launch Windows command shim
- cannot safely launch Windows command shim
- non-Node Windows command shim
AI-assisted analysis of JuliusBrussee/caveman@3ee70a1026 (2026-09-20).
Data as JSON: /api/errors/3547a6aa2a8a49f9.
Report an issue: GitHub.
Appendix: source
Thrown at packages/subagent-tax/lib/process-tree.mjs:57
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 = /^[A-Za-z]:[\\/]/.test(relativeScript)
? relativeScript
: 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,
{View on GitHub (pinned to 3ee70a1026)