{"record":{"id":"3547a6aa2a8a49f9","repo":"JuliusBrussee/caveman","slug":"cannot-safely-launch-non-node-windows-command-shim-process","errorCode":null,"errorMessage":"cannot safely launch non-Node Windows command shim: ${executable}","messagePattern":"cannot safely launch non-Node Windows command shim: (.+?)","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/subagent-tax/lib/process-tree.mjs","lineNumber":57,"sourceCode":"  return null;\n}\n\nexport function portableProcessInvocation(\n  command,\n  args,\n  { platform = process.platform, env = process.env, execPath = process.execPath } = {},\n) {\n  if (platform !== \"win32\") return { command, args: [...args] };\n  const executable = resolveWindowsCommand(command, env);\n  if (!executable) throw Object.assign(new Error(`command not found: ${command}`), { code: \"ENOENT\" });\n  if (!/\\.(?:cmd|bat)$/i.test(executable)) return { command: executable, args: [...args] };\n  const stat = statSync(executable);\n  if (!stat.isFile() || stat.size > 256 * 1024) {\n    throw new Error(`cannot safely launch Windows command shim: ${executable}`);\n  }\n  const relativeScript = parseWindowsNodeShim(readFileSync(executable, \"utf8\"));\n  if (!relativeScript) {\n    throw new Error(`cannot safely launch non-Node Windows command shim: ${executable}`);\n  }\n  const script = /^[A-Za-z]:[\\\\/]/.test(relativeScript)\n    ? relativeScript\n    : resolve(dirname(executable), ...relativeScript.split(/[\\\\/]+/));\n  if (!statSync(script).isFile()) throw new Error(`Windows command shim target is missing: ${script}`);\n  return { command: execPath, args: [script, ...args] };\n}\n\nexport function harnessSpawnOptions(platform = process.platform) {\n  return {\n    detached: platform !== \"win32\",\n    windowsHide: true,\n  };\n}\n\nexport function forceKillTree(\n  child,\n  {","sourceCodeStart":39,"sourceCodeEnd":75,"githubUrl":"https://github.com/JuliusBrussee/caveman/blob/3ee70a102609e550bd2e68004bf5990a9341c851/packages/subagent-tax/lib/process-tree.mjs#L39-L75","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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."],"exampleFix":"// before\nspawn(\"deploy.cmd\", [\"--prod\"]); // non-Node batch shim, throws\n// after\nspawn(\"powershell.exe\", [\"-File\", \"deploy.ps1\", \"--prod\"]);","handlingStrategy":"fallback","validationCode":"import { readFileSync } from \"node:fs\";\nfunction isNodeShim(executable) {\n  if (!/\\.(?:cmd|bat)$/i.test(executable)) return true;\n  try { return Boolean(readFileSync(executable, \"utf8\").match(/node/i) && /%~dp0|\"%~dp0\"/.test(readFileSync(executable, \"utf8\"))); }\n  catch { return false; }\n}","typeGuard":null,"tryCatchPattern":"try {\n  child = portableProcessInvocation(command, args, env, process.platform);\n} catch (e) {\n  if (e.message.includes(\"non-Node Windows command shim\")) {\n    // run the tool natively instead of through its batch wrapper\n    child = spawnNativeAlternative(command, args);\n  } else throw e;\n}","preventionTips":["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."],"tags":["windows","process-spawn","shim"],"backgroundTag":"unsupported-operation","analyzedSha":"3ee70a102609e550bd2e68004bf5990a9341c851","analyzedAt":"2026-09-20T15:53:39.229Z","contentChangedAt":"2026-09-20T15:53:39.229Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}