JuliusBrussee/caveman · error · Error
Windows command shim target is missing
Error message
Windows command shim target is missing: ${script} What it means
After parsing a Windows Node shim, the library resolves the shim's relative target script to an absolute path and verifies it exists with statSync(script).isFile(). If the target file is missing (stale shim pointing at a removed/moved script, or a bad install), it throws this error naming the resolved script path rather than letting spawn fail obscurely.
Solutions
- Reinstall dependencies to regenerate shims and their targets: rm -rf node_modules package-lock (as appropriate) then npm install / npm ci.
- Verify the reported script path exists; if not, the owning package is broken — reinstall that single package (npm install <pkg> --force).
- Check that the package version's bin entry matches the shim; clear stale shims after an upgrade.
- As a workaround, invoke the target script via node directly once you know its real location.
Example fix
// before: stale shim -> target removed
spawn("mytool", []); // shim target missing
// after
// regenerate: npm ci
spawn("mytool", []); // shim and target consistent Defensive patterns
Strategy: validation
Validate before calling
import { statSync, existsSync } from "node:fs";
import { dirname, resolve } from "node:path";
function shimTargetExists(executable, relativeScript) {
const script = /^[A-Za-z]:[\\/]/.test(relativeScript)
? relativeScript
: resolve(dirname(executable), ...relativeScript.split(/[\\/]+/));
return existsSync(script) && statSync(script).isFile();
} Try / catch
try {
child = portableProcessInvocation(command, args, env, process.platform);
} catch (e) {
if (e.message.startsWith("Windows command shim target is missing")) {
console.error("Stale node_modules shim — run npm ci and retry");
throw e;
} else throw e;
} Prevention
- Run npm ci in CI/fresh checkouts so shims and targets stay in sync.
- Reinstall dependencies after switching branches or upgrading packages that own bin entries.
- Never hand-delete files inside node_modules; regenerate the tree instead.
When it happens
Trigger: portableProcessInvocation() on win32 where the .cmd shim parses to a relative script path that, resolved against dirname(executable), does not exist or is not a file — e.g. node_modules/<pkg>/bin/x.cmd pointing to a lib file deleted by a partial install or pruned dependency.
Common situations: node_modules partially deleted or out of sync with package.json; a package upgraded and its bin target renamed while an old shim remained; pnpm store pruning; switching branches without reinstalling dependencies.
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 Windows command shim
- cannot safely launch Windows command shim
- Windows command shim target is missing
AI-assisted analysis of JuliusBrussee/caveman@3ee70a1026 (2026-09-20).
Data as JSON: /api/errors/d8acf46d13a57bca.
Report an issue: GitHub.
Appendix: source
Thrown at packages/subagent-tax/lib/process-tree.mjs:62
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,
{
platform = process.platform,
kill = process.kill,
taskkill = spawnSync,
} = {},
) {View on GitHub (pinned to 3ee70a1026)