JuliusBrussee/caveman · 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, `portableInvocation` resolves the shim's target script (absolute if the shim says so, otherwise relative to the shim's directory) and stats it at packages/pi-extension/src/portable-command.ts:94. If the target is not a regular file, the shim is dangling — it would launch Node against a nonexistent script — so the library throws this Error with the resolved path.

Solutions

  1. Reinstall the tool the shim belongs to so the target script is restored.
  2. Delete stale shims from the global/local bin directory and reinstall cleanly.
  3. Verify the resolved target path exists (`fs.existsSync(scriptPath)`) before invoking, and point config at the correct entry.

Example fix

// before
// dangling shim: my-cli.cmd -> ./node_modules/my-cli/bin/cli.js (deleted)
// after
npm i -D my-cli   // restores node_modules/my-cli/bin/cli.js
Defensive patterns

Strategy: validation

Validate before calling

import { statSync } from 'node:fs';
function shimTargetExists(shimPath: string, target: string) {
  const resolved = /^[A-Za-z]:[\\/]/.test(target) ? target : resolve(dirname(shimPath), target);
  try { return statSync(resolved).isFile(); } catch { return false; }
}

Type guard

const fileExists = (p: string): boolean => { try { return statSync(p).isFile(); } catch { return false; } };

Try / catch

try {
  const inv = portableInvocation(command, args, env);
} catch (e) {
  if (e instanceof Error && /shim target is missing/.test(e.message)) {
    console.error(`${command} shim is dangling; reinstall the package.`);
    throw e;
  }
  throw e;
}

Prevention

When it happens

Trigger: A `.cmd` shim referencing a JS entry point that no longer exists (package uninstalled/renamed, node_modules pruned, or the shim written for a different install layout).

Common situations: Partial `npm uninstall`/upgrade leaving orphaned shims; moving or renaming a project directory that a shim points into; pnpm/yarn layouts differing from npm's expected paths.

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


AI-assisted analysis of JuliusBrussee/caveman@3ee70a1026 (2026-09-20). Data as JSON: /api/errors/2ad11534b0e65ba3. Report an issue: GitHub.

Appendix: source

Thrown at packages/pi-extension/src/portable-command.ts:94

  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)