JuliusBrussee/caveman · error · Error

Windows command shim target is missing: ${script}

Error message

Windows command shim target is missing: ${script}

What it means

The final step of Windows shim handling resolves the Node script referenced inside a verified .cmd shim and statSyncs it. If that target .js file does not exist as a regular file, the library throws 'Windows command shim target is missing' rather than launching node with a nonexistent script. This typically means the shim is stale relative to the package contents.

Source

Thrown at packages/agent/src/portable-process.ts:63

    env?: NodeJS.ProcessEnv;
    execPath?: string;
  } = {},
): PortableInvocation {
  const platform = options.platform ?? process.platform;
  const env = options.env ?? process.env;
  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 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: options.execPath ?? process.execPath, args: [script, ...args] };
}

export function hostShellInvocation(
  source: string,
  platform: NodeJS.Platform = process.platform,
  env: NodeJS.ProcessEnv = process.env,
): PortableInvocation {
  if (platform === "win32") {
    return {
      command: envValue(env, "ComSpec") ?? "cmd.exe",
      args: ["/d", "/s", "/c", source],
    };
  }
  return { command: "/bin/sh", args: ["-c", source] };
}

export function killProcessTree(

View on GitHub (pinned to 27d5a3981a)

Solutions

  1. Reinstall dependencies so shims and targets are regenerated consistently: rm -rf node_modules && npm install
  2. Verify the target manually: open the .cmd, find the script path, confirm the file exists
  3. In monorepos, run the package's bin via the workspace path instead of a hoisted .bin shim
  4. Check for case-sensitivity mismatches after copying a project from macOS/Windows to Linux or vice versa

Example fix

# before
# .bin/build-tool.cmd points to ..\..\lib\cli.js which does not exist

# after
rm -rf node_modules package-lock.json.orig && npm install
# shim and target are regenerated in sync
Defensive patterns

Strategy: retry

Validate before calling

import { statSync, readFileSync } from "node:fs";
import { dirname, resolve } from "node:path";
function shimTargetExists(executable: string): boolean {
  const body = readFileSync(executable, "utf8");
  const m = body.match(/["']([^"']*\.js)["']/);
  if (!m) return false;
  try { return statSync(resolve(dirname(executable), m[1])).isFile(); } catch { return false; }
}

Try / catch

try {
  const inv = portableInvocation(cmd, args);
} catch (e) {
  if (e instanceof Error && e.message.includes("shim target is missing")) {
    // retry once after reinstalling deps or fall back to the direct script path
  }
  throw e;
}

Prevention

When it happens

Trigger: The .cmd wrapper points at ..\some-script.js that was deleted, renamed, or never installed — e.g. after a partial install, a package downgrade that changed file layout, or a git-clean that removed untracked files under node_modules.

Common situations: Partial or interrupted npm install, node_modules pruned by a disk-cleanup tool, monorepo hoisting moved the real script while a stale .bin shim remained, or copying node_modules between machines with missing files.

Related errors


AI-assisted analysis of JuliusBrussee/caveman@27d5a3981a (2026-08-15). Data as JSON: /api/errors/bb221d7768f255b6. Report an issue: GitHub.