JuliusBrussee/caveman · error · Error
Windows command shim target is missing
Error message
Windows command shim target is missing: ${script} What it means
Thrown by portableInvocation() on Windows when the Node shim embedded in a .cmd/.bat points to a script file that does not exist: parseWindowsNodeShim extracted the target path, it was resolved (absolute, or relative to the shim's directory), but statSync(script).isFile() fails. This indicates a broken or partially uninstalled package whose shim survived while its entry script was removed.
Solutions
- Reinstall the package globally: `npm install -g <package>` to regenerate shim + target script.
- Check the referenced script path in the error; restore the missing file or fix npm's global prefix (`npm config get prefix`).
- Align node version managers (nvm/fnm/volta) so the shim's target exists under the active node install.
- Remove stale shims from the global bin directory for packages you no longer use.
Example fix
// before
C:\Users\me\AppData\Roaming\npm\oldtool.cmd -> ..\lib\node_modules\oldtool\cli.js (missing) // throws
// after
npm install -g oldtool // regenerates shim and cli.js
invocation("oldtool") // spawns: node ...\oldtool\cli.js Defensive patterns
Strategy: validation
Validate before calling
import { statSync, existsSync } from "fs";
function shimTargetExists(shimPath: string): boolean {
try {
const content = readFileSync(shimPath, "utf8");
const m = content.match(/"%~dp0\\\\?([^\"]+\.js)"/i) || content.match(/node[^\r\n]*?([\w.\\/-]+\.js)/i);
if (!m) return true; // not a node shim; other errors apply
const target = require("path").resolve(require("path").dirname(shimPath), m[1]);
return existsSync(target) && statSync(target).isFile();
} catch { return false; }
} Try / catch
try {
const inv = invocation(cmd, args);
spawn(inv.command, inv.args);
} catch (e) {
if (e instanceof Error && e.message.startsWith("Windows command shim target is missing")) {
console.error("Broken install: run `npm install -g <pkg>` to regenerate the shim target", e.message);
} else throw e;
} Prevention
- Reinstall packages globally after switching node version managers
- Keep npm's global prefix stable; avoid moving node install directories
- Prune shims of uninstalled packages from the global bin dir
- Verify shim -> script integrity after cloning/moving environments
When it happens
Trigger: platform === 'win32', command resolves to a valid small Node .cmd shim, the extracted script path resolves to a non-existent or non-file location (package uninstalled, node_modules pruned, drive letter changed, wrong global prefix).
Common situations: node_modules partially deleted while global prefix shims remain, switching nvm/node versions so the shim references a removed install, or moving/copying an npm global directory without its target layout.
Understand the failure class
Background: "File not found" and ENOENT errors: why libraries can't find a file that should exist — this error's family across 50 libraries.
Related errors
- cannot safely launch non-Node Windows command shim
- cannot safely launch non-Node Windows command shim
- cannot safely launch non-Node 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/4bd8098c73dc175a.
Report an issue: GitHub.
Appendix: source
Thrown at packages/cli/src/portable-command.ts:75
platform: NodeJS.Platform = process.platform,
env: NodeJS.ProcessEnv = process.env,
): PortableInvocation {
if (platform !== "win32") return { command, args: [...args] };
const executable = resolveWindowsCommand(command, env) ?? command;
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 shimScript = parseWindowsNodeShim(readFileSync(executable, "utf8"));
if (!shimScript) {
throw new Error(`cannot safely launch non-Node Windows command shim: ${executable}; install a native .exe`);
}
const script = /^[A-Za-z]:[\\/]/.test(shimScript)
? shimScript
: resolve(dirname(executable), ...shimScript.split(/[\\/]+/));
if (!statSync(script).isFile()) {
throw new Error(`Windows command shim target is missing: ${script}`);
}
return { command: process.execPath, args: [script, ...args] };
}
View on GitHub (pinned to 3ee70a1026)