{"record":{"id":"f3124a80fa709e67","repo":"JuliusBrussee/caveman","slug":"registry-output-has-no-valid-registry-sha256","errorCode":null,"errorMessage":"registry output has no valid registry_sha256","messagePattern":"registry output has no valid registry_sha256","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/agent/src/cli.ts","lineNumber":1114,"sourceCode":"  const command = process.env.CAVEMAN_ENGINE_BIN ?? \"caveman-engine\";\n  try {\n    const env = buildEngineEnv();\n    const invocation = portableInvocation(command, [\"registry\"], { 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 {\n      registry_sha256?: unknown;\n      capabilities?: Array<{\n        transform_id?: unknown;\n        eligible_segment_kinds?: unknown;\n      }>;\n    };\n    if (typeof parsed.registry_sha256 !== \"string\" || !/^[0-9a-f]{64}$/.test(parsed.registry_sha256)) {\n      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(","sourceCodeStart":1096,"sourceCodeEnd":1132,"githubUrl":"https://github.com/JuliusBrussee/caveman/blob/27d5a3981a347890211bb1bf2439e5c821a63bc9/packages/agent/src/cli.ts#L1096-L1132","documentation":"Thrown while parsing the output of the caveman engine's transform-registry command. The CLI spawns the engine binary (10s timeout, 2 MiB buffer), JSON-parses stdout, and requires `registry_sha256` to be a string matching `^[0-9a-f]{64}$`. If the field is missing, not a string, or not a 64-char lowercase hex digest, this error is thrown. A matching failure is wrapped into `cave_transform_registry_unavailable` by the outer catch.","triggerScenarios":"`CAVEMAN_ENGINE_BIN` (or the default `caveman-engine` on PATH) resolves to a binary that prints JSON without a valid `registry_sha256`: a different tool by the same name, an engine version with a changed output schema, a shell shim that prepends banner text making the JSON parse land elsewhere, or a partial/errored engine output.","commonSituations":"A stale engine from before an output-schema change; PATH shadowing by an unrelated `caveman-engine`; a wrapper script that logs to stdout before the JSON; a truncated registry file inside a broken engine install.","solutions":["Run the registry command manually (`$CAVEMAN_ENGINE_BIN <registry args>` or `caveman-engine`) and inspect stdout — `registry_sha256` must be exactly 64 lowercase hex chars.","Reinstall/refresh the engine with `caveman setup` so the binary matches the framework version.","If a wrapper or shim adds stdout noise, point `CAVEMAN_ENGINE_BIN` at the real binary.","Verify engine and framework versions agree via `caveman doctor`."],"exampleFix":"# before: shim pollutes stdout\nCAVEMAN_ENGINE_BIN=./engine-shim.sh\n\n# after: point at the real binary\nCAVEMAN_ENGINE_BIN=/usr/local/bin/caveman-engine","handlingStrategy":"validation","validationCode":"function isValidRegistrySha256(v: unknown): boolean {\n  return typeof v === \"string\" && /^[0-9a-f]{64}$/.test(v);\n}\n// before building, probe the engine once and assert isValidRegistrySha256(parsed.registry_sha256)","typeGuard":"function isHex64(v: unknown): v is string {\n  return typeof v === \"string\" && /^[0-9a-f]{64}$/.test(v);\n}","tryCatchPattern":"try {\n  await build(args);\n} catch (error) {\n  if (error instanceof Error && error.message.startsWith(\"cave_transform_registry_unavailable\")) {\n    // inspect the parenthesized cause: bad registry_sha256 means engine/framework schema mismatch -> caveman setup\n  } else throw error;\n}","preventionTips":["Install the engine via `caveman setup` and keep it version-locked with the framework.","Never wrap the engine binary in a script that writes to stdout.","Run `caveman doctor` after engine changes."],"tags":["engine","registry","external-process","parsing"],"backgroundTag":null,"analyzedSha":"27d5a3981a347890211bb1bf2439e5c821a63bc9","analyzedAt":"2026-08-15T09:26:11.751Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}