{"record":{"id":"716771fc228f5327","repo":"JuliusBrussee/caveman","slug":"cave-transform-registry-unavailable-run-caveman-s","errorCode":null,"errorMessage":"cave_transform_registry_unavailable: run caveman setup or set CAVEMAN_ENGINE_BIN (${error instanceof Error ? error.message : String(error)})","messagePattern":"cave_transform_registry_unavailable: run caveman setup or set CAVEMAN_ENGINE_BIN \\((.+?)\\)","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/agent/src/cli.ts","lineNumber":1132,"sourceCode":"      throw new Error(\"registry output has no valid registry_sha256\");\n    }\n    if (!Array.isArray(parsed.capabilities) || parsed.capabilities.length === 0) {\n      throw new Error(\"registry output has no capabilities\");\n    }\n    const capabilities = parsed.capabilities.map((capability): TransformCapability => {\n      if (typeof capability.transform_id !== \"string\" ||\n          !Array.isArray(capability.eligible_segment_kinds) ||\n          capability.eligible_segment_kinds.some((kind) => typeof kind !== \"string\")) {\n        throw new Error(\"registry output has invalid capability\");\n      }\n      return {\n        transformID: capability.transform_id,\n        segmentKinds: capability.eligible_segment_kinds as TransformCapability[\"segmentKinds\"],\n      };\n    });\n    return { sha256: parsed.registry_sha256, capabilities };\n  } catch (error) {\n    throw new Error(\n      `cave_transform_registry_unavailable: run caveman setup or set CAVEMAN_ENGINE_BIN (${error instanceof Error ? error.message : String(error)})`,\n    );\n  }\n}\n\nasync function engineEntitled(): Promise<boolean> {\n  const command = process.env.CAVEMAN_CLI_BIN ?? \"caveman\";\n  try {\n    const env = buildRuntimeControlEnv();\n    const invocation = portableInvocation(command, [\"status\", \"--json\"], { env });\n    const { stdout } = await execFileAsync(invocation.command, [...invocation.args], {\n      encoding: \"utf8\",\n      env,\n      maxBuffer: 2 << 20,\n      timeout: 10_000,\n    });\n    const parsed = JSON.parse(stdout) as { mode?: unknown; seat?: { entitled?: unknown } };\n    return parsed.seat?.entitled === true && parsed.mode === \"compress\";","sourceCodeStart":1114,"sourceCodeEnd":1150,"githubUrl":"https://github.com/JuliusBrussee/caveman/blob/27d5a3981a347890211bb1bf2439e5c821a63bc9/packages/agent/src/cli.ts#L1114-L1150","documentation":"Catch-all wrapper around the whole transform-registry load: spawning the engine binary, its timeout (10s), non-zero exit, stdout too large (>2 MiB), invalid JSON, or any of the per-field validation errors above. The message tells you the two supported remedies — run `caveman setup` to install the engine, or point `CAVEMAN_ENGINE_BIN` at an existing binary — and appends the underlying error text for diagnosis.","triggerScenarios":"`caveman-engine` not on PATH and `CAVEMAN_ENGINE_BIN` unset (spawn ENOENT); the engine exceeds the 10-second timeout on first-run initialization; engine exits non-zero (broken install); stdout is not JSON (crash traceback); any of the registry_sha256/capabilities validation failures.","commonSituations":"Fresh machine without `caveman setup`; CI container missing the engine; corporate environment blocking engine download; slow cold start of the engine exceeding 10s on constrained runners; `CAVEMAN_ENGINE_BIN` pointing at a removed path.","solutions":["Run `caveman setup` to install/repair the engine and registry.","If the engine exists elsewhere, set `CAVEMAN_ENGINE_BIN=/path/to/caveman-engine`.","Read the parenthesized cause: ENOENT → missing binary; timeout → pre-warm the engine once manually; SyntaxError → binary prints non-JSON output.","Verify with `caveman doctor` that the engine registry check passes before building."],"exampleFix":"# before\nnpm run build\n# Error: cave_transform_registry_unavailable: ... spawn caveman-engine ENOENT\n\n# after\ncaveman setup\n# or: export CAVEMAN_ENGINE_BIN=/opt/caveman/bin/caveman-engine\nnpm run build","handlingStrategy":"retry","validationCode":"import { access } from \"node:fs/promises\";\n\nasync function engineAvailable(): Promise<boolean> {\n  const bin = process.env.CAVEMAN_ENGINE_BIN ?? \"caveman-engine\";\n  if (process.env.CAVEMAN_ENGINE_BIN) {\n    try { await access(process.env.CAVEMAN_ENGINE_BIN); return true; } catch { return false; }\n  }\n  return false; // fall back to `command -v caveman-engine` in shell","typeGuard":null,"tryCatchPattern":"try {\n  await build(args);\n} catch (error) {\n  if (error instanceof Error && error.message.startsWith(\"cave_transform_registry_unavailable\")) {\n    // read the cause: ENOENT -> set CAVEMAN_ENGINE_BIN or run caveman setup; timeout -> pre-warm engine; then retry once\n  } else throw error;\n}","preventionTips":["Run `caveman setup` as part of environment provisioning (devcontainer, CI image).","Set CAVEMAN_ENGINE_BIN explicitly in CI to avoid PATH surprises.","Pre-warm the engine once on cold runners to avoid the 10s first-start timeout."],"tags":["engine","setup","environment","external-process"],"backgroundTag":null,"analyzedSha":"27d5a3981a347890211bb1bf2439e5c821a63bc9","analyzedAt":"2026-08-15T09:26:11.751Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}