{"record":{"id":"86ad08ab61ca5106","repo":"JuliusBrussee/caveman","slug":"registry-output-has-no-capabilities","errorCode":null,"errorMessage":"registry output has no capabilities","messagePattern":"registry output has no capabilities","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"packages/agent/src/cli.ts","lineNumber":1117,"sourceCode":"    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(\n      `cave_transform_registry_unavailable: run caveman setup or set CAVEMAN_ENGINE_BIN (${error instanceof Error ? error.message : String(error)})`,\n    );\n  }","sourceCodeStart":1099,"sourceCodeEnd":1135,"githubUrl":"https://github.com/JuliusBrussee/caveman/blob/3ee70a102609e550bd2e68004bf5990a9341c851/packages/agent/src/cli.ts#L1099-L1135","documentation":"loadTransformRegistry() requires the engine's 'registry' JSON output to contain a non-empty capabilities array. If capabilities is missing, not an array, or empty, it throws 'registry output has no capabilities'. An empty registry means no transform can be routed, so the framework fails closed instead of producing a useless lock/plan.","triggerScenarios":"Calling loadTransformRegistry (during lock checks or compile) when the engine binary's registry JSON has no capabilities array or an empty one — e.g. an engine build compiled without transforms, or a stub/mocked CAVEMAN_ENGINE_BIN.","commonSituations":"CAVEMAN_ENGINE_BIN pointing at a minimal/custom engine build with no registered transforms; an engine version that renamed the capabilities field; running a placeholder script during tests.","solutions":["Run 'caveman setup' to install the full engine with its transform registry","Point CAVEMAN_ENGINE_BIN at the official caveman-engine binary that registers transforms","Run 'caveman-engine registry' manually and confirm the JSON contains a non-empty capabilities array"],"exampleFix":"// before\n\"CAVEMAN_ENGINE_BIN\": \"/tmp/stub-engine\"  // prints {\"registry_sha256\":\"...\"}\n// after\n\"CAVEMAN_ENGINE_BIN\": \"/home/me/.caveman/bin/caveman-engine\" // full engine","handlingStrategy":"type-guard","validationCode":"const parsed = JSON.parse(await engineRegistryOutput());\nif (!Array.isArray(parsed.capabilities) || parsed.capabilities.length === 0) {\n  console.error(\"engine registers no transforms; install the full engine via caveman setup\");\n}","typeGuard":"function hasCapabilities(parsed: unknown): parsed is { registry_sha256: string; capabilities: unknown[] } {\n  const p = parsed as { capabilities?: unknown };\n  return Array.isArray(p?.capabilities) && p.capabilities.length > 0;\n}","tryCatchPattern":"try {\n  await loadTransformRegistry();\n} catch (error) {\n  if ((error as Error).message.includes(\"no capabilities\")) {\n    await runCavemanSetup(); // full engine, not a stub build\n    return await loadTransformRegistry();\n  }\n  throw error;\n}","preventionTips":["Never point CAVEMAN_ENGINE_BIN at stub/minimal engine builds","Verify registry contents after any custom engine build","Keep engine and adapter versions matched"],"tags":["engine","registry","validation","empty-result"],"backgroundTag":"unexpected-response-shape","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"}