{"record":{"id":"34ae0da0e73116fe","repo":"JuliusBrussee/caveman","slug":"pi-extension-not-found-at-extension-set-caveman-pi-extension","errorCode":null,"errorMessage":"Pi extension not found at ${extension}; set CAVEMAN_PI_EXTENSION or run the CLI build step","messagePattern":"Pi extension not found at (.+?); set CAVEMAN_PI_EXTENSION or run the CLI build step","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/cli/src/index.ts","lineNumber":10788,"sourceCode":"}\n\n// resolveDelegateMcpCommand locates the dependency-free caveman-delegate stdio\n// server (CAVEMAN_DELEGATE_MCP override, else the copy shipped alongside the\n// CLI). Null when the script is missing — callers must not register a dead entry.\nfunction resolveDelegateMcpCommand(): { command: string; args: string[] } | null {\n  const candidates = [\n    process.env.CAVEMAN_DELEGATE_MCP || \"\",\n    join(dirname(fileURLToPath(import.meta.url)), \"caveman-delegate-mcp.mjs\"),\n  ].filter(Boolean);\n  const script = candidates.find((c) => existsSync(c));\n  return script ? { command: process.execPath, args: [script] } : null;\n}\n\nfunction resolvePiExtension(): string {\n  const extension = process.env.CAVEMAN_PI_EXTENSION?.trim()\n    || join(dirname(fileURLToPath(import.meta.url)), \"caveman-pi-extension.mjs\");\n  if (!existsSync(extension)) {\n    throw new Error(`Pi extension not found at ${extension}; set CAVEMAN_PI_EXTENSION or run the CLI build step`);\n  }\n  return extension;\n}\n\nfunction buildPiWrapArgs(cmdArgs: string[], env: NodeJS.ProcessEnv, gw: string): string[] {\n  const extension = resolvePiExtension();\n  const { cmd, pre } = cavemanInvocation();\n  env.CAVEMAN_PI_HOOK_CMD = JSON.stringify([cmd, ...pre]);\n  env.CAVE_GATEWAY_URL = gw;\n  // The profile's injection block declares the loader flag; using it here keeps the\n  // compiled registry the single source of truth for how the asset is loaded.\n  const profile = AGENTS.find((a) => a.id === \"pi\");\n  const loaderFlag = profile?.injection.method === \"native-extension\" ? profile.injection.loader_flag : \"--extension\";\n  return [loaderFlag, extension, ...cmdArgs];\n}\n\nconst HERMES_MCP_BEGIN = \"# >>> caveman:mcp\";\nconst HERMES_MCP_END = \"# <<< caveman:mcp\";","sourceCodeStart":10770,"sourceCodeEnd":10806,"githubUrl":"https://github.com/JuliusBrussee/caveman/blob/3ee70a102609e550bd2e68004bf5990a9341c851/packages/cli/src/index.ts#L10770-L10806","documentation":"When wrapping Pi-based commands, the CLI injects a bundled extension script `caveman-pi-extension.mjs` located next to the CLI module. `resolvePiExtension()` throws this error when neither the CAVEMAN_PI_EXTENSION env var nor the default build-output path points at an existing file, i.e. the extension artifact was never built or was moved.","triggerScenarios":"Running any pi-wrapped command where: CAVEMAN_PI_EXTENSION is set to a nonexistent/misspelled path, or the default path (dirname of the CLI module + caveman-pi-extension.mjs) does not exist because the build step was skipped or artifacts were pruned (e.g. running from a source checkout or a slim package install).","commonSituations":"Running the CLI from a repo clone without running the build; installing a trimmed package that excludes .mjs assets; CI caching node_modules without build outputs; typo in CAVEMAN_PI_EXTENSION or stale path after an upgrade.","solutions":["Run the CLI's build step so caveman-pi-extension.mjs is emitted next to the module","Set CAVEMAN_PI_EXTENSION to the absolute path of an existing extension file (verify with ls)","Reinstall/upgrade the CLI package so bundled assets are present","If the env var is set, unset it to fall back to the default path"],"exampleFix":"// before\nCAVEMAN_PI_EXTENSION=./old-ext.mjs caveman ...\n// after\ncaveman build  # emits dist/caveman-pi-extension.mjs\n# or\nexport CAVEMAN_PI_EXTENSION=/abs/path/caveman-pi-extension.mjs","handlingStrategy":"validation","validationCode":"const ext = process.env.CAVEMAN_PI_EXTENSION?.trim()\n  || join(dirname(fileURLToPath(import.meta.url)), \"caveman-pi-extension.mjs\");\nif (!existsSync(ext)) throw new Error(`run the build step first; expected ${ext}`);","typeGuard":null,"tryCatchPattern":"try {\n  await runPiWrap(args);\n} catch (e) {\n  if ((e as Error).message.includes(\"Pi extension not found\")) {\n    await build(); // then retry once\n    await runPiWrap(args);\n  } else throw e;\n}","preventionTips":["Always run the build step after cloning or upgrading the CLI","In CI, cache build outputs alongside node_modules","If overriding via CAVEMAN_PI_EXTENSION, assert the file exists in setup scripts","Prefer full package installs over trimmed/pruned asset installs"],"tags":["missing-file","build","env-var"],"backgroundTag":"file-not-found","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"}