JuliusBrussee/caveman · error

cave_claude_subagent_bridge_unavailable

cave_claude_subagent_bridge_unavailable

Error message

cave_claude_subagent_bridge_unavailable

What it means

Fail-closed guard in runClaudeAgentWithOptions: the definition includes a tool whose runtime kind is 'subagent', but the Claude runtime has no subagent bridge. The run aborts rather than registering a tool that could not dispatch.

Solutions

  1. Strip subagent-runtime tools from definitions routed to the Claude runtime
  2. Run these definitions on a harness that implements subagent dispatch
  3. Flatten the subagent tool into a plain read/inline tool the Claude lane supports
Defensive patterns

Strategy: validation

When it happens

Trigger: Thrown at packages/agent/src/claude-runtime.ts:98 when the library encounters an invalid state.

Common situations: See trigger scenarios.


AI-assisted analysis of JuliusBrussee/caveman@3ee70a1026 (2026-09-20). Data as JSON: /api/errors/8bf5e235023802e4. Report an issue: GitHub.

Appendix: source

Thrown at packages/agent/src/claude-runtime.ts:98

async function runClaudeAgentWithOptions(
  definition: AgentDefinition,
  input: string,
  options: ClaudeInternalRunOptions,
): Promise<RunResult> {
  if (options.lockedBuild !== undefined && options.candidatePlan !== undefined) {
    throw new Error("cave_execution_authorization_ambiguous");
  }
  if (options.candidatePlan !== undefined) {
    throw new Error("cave_claude_candidate_execution_unavailable");
  }
  if (options.lockedBuild !== undefined) {
    throw new Error("cave_claude_locked_execution_unavailable");
  }
  if (definition.memory !== undefined) {
    throw new Error("cave_claude_memory_bridge_unavailable");
  }
  if (definition.tools.some((item) => item.runtime?.kind === "subagent")) {
    throw new Error("cave_claude_subagent_bridge_unavailable");
  }
  const unsupportedTool = definition.tools.find((item) =>
    item.effect !== "read" || item.result !== "inline");
  if (unsupportedTool !== undefined) {
    throw new Error(`cave_claude_tool_contract_unsupported:${unsupportedTool.name}`);
  }
  if (options.maxTurns !== undefined &&
      (!Number.isSafeInteger(options.maxTurns) || options.maxTurns <= 0 || options.maxTurns > 1_000)) {
    throw new Error("cave_claude_max_turns_invalid");
  }
  if (options.maxBudgetUsd !== undefined &&
      (!Number.isFinite(options.maxBudgetUsd) || options.maxBudgetUsd <= 0)) {
    throw new Error("cave_claude_max_budget_invalid");
  }
  const rootDir = resolve(options.rootDir ?? process.cwd());
  const lowered = await lowerAgentContext(definition, { rootDir, input });
  const bill = contextBill(lowered.ir);
  const selected = resolveClaudeModel(definition, rootDir);

View on GitHub (pinned to 3ee70a1026)