JuliusBrussee/caveman · error · Error

cave_claude_output_budget_too_small_for_reasoning

Error message

cave_claude_output_budget_too_small_for_reasoning

What it means

For models with "manual" thinking capability (claude-haiku-4-5, sonnet-4-5, opus-4-1/4-5), the framework maps reasoning level to a thinking budget (high=8192, medium=4096, low=1024 tokens). If you also set outputMaxTokens and it is <= the thinking budget, the model would spend its entire output allowance on reasoning and have nothing left for the answer, so the option combination is rejected up front.

Source

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

}

function claudeReasoningOptions(
  model: string,
  reasoning: AgentDefinition["reasoning"],
  outputMaxTokens: number | undefined,
): Pick<ClaudeSDKOptions, "thinking" | "effort"> {
  if (reasoning === "off") return { thinking: { type: "disabled" } };
  const capability = claudeThinkingCapability(model);
  if (capability === "adaptive") {
    return {
      thinking: { type: "adaptive" },
      effort: claudeEffort(reasoning),
    };
  }
  if (capability === "manual") {
    const budgetTokens = reasoning === "high" ? 8_192 : reasoning === "medium" ? 4_096 : 1_024;
    if (outputMaxTokens !== undefined && outputMaxTokens <= budgetTokens) {
      throw new Error("cave_claude_output_budget_too_small_for_reasoning");
    }
    return { thinking: { type: "enabled", budgetTokens } };
  }
  throw new Error(`cave_claude_reasoning_capability_unknown:${model}`);
}

function claudeThinkingCapability(model: string): "adaptive" | "manual" | "unknown" {
  if (/^claude-(?:haiku-4-5|sonnet-4-5|opus-4-(?:1|5))(?:-\d{8})?$/.test(model)) {
    return "manual";
  }
  if (/^claude-(?:sonnet|opus)-4-[678](?:-\d{8})?$/.test(model) ||
      /^claude-(?:fable|mythos|sonnet|opus)-5(?:-\d+)?$/.test(model)) {
    return "adaptive";
  }
  return "unknown";
}

// Accepts ANY result subtype: error subtypes (error_max_turns, …) carry the

View on GitHub (pinned to 27d5a3981a)

Solutions

  1. Raise outputMaxTokens above the reasoning budget: use > 8192 for reasoning:"high", > 4096 for "medium", > 1024 for "low".
  2. Or set reasoning: "off" (thinking disabled) if a small output cap is the priority.
  3. Or switch to an adaptive-thinking model (e.g. claude-sonnet-4-6, claude-sonnet-5) where effort-based thinking has no token-budget coupling.

Example fix

// before
await run({ prompt, reasoning: "medium", outputMaxTokens: 4000 });

// after
await run({ prompt, reasoning: "medium", outputMaxTokens: 16384 });
// or: await run({ prompt, reasoning: "off", outputMaxTokens: 4000 });
Defensive patterns

Strategy: validation

Validate before calling

const REASONING_BUDGET = { low: 1024, medium: 4096, high: 8192 } as const;
function outputBudgetOk(reasoning: keyof typeof REASONING_BUDGET | "off", outputMaxTokens?: number): boolean {
  if (reasoning === "off" || outputMaxTokens === undefined) return true;
  return outputMaxTokens > REASONING_BUDGET[reasoning];
}

Prevention

When it happens

Trigger: Calling the Claude run with reasoning set to low/medium/high (not "off"), a manually-thinking model, and an options.outputMaxTokens <= 1024/4096/8192 respectively. Example: { reasoning: "medium", outputMaxTokens: 4000 } → 4000 <= 4096 → throw.

Common situations: Tightening outputMaxTokens to cap cost while leaving reasoning on; porting a config from an adaptive-thinking model (opus-4-6+, sonnet-5) where the constraint doesn't exist; defaults that set a small max_tokens from an older provider config.

Related errors


AI-assisted analysis of JuliusBrussee/caveman@27d5a3981a (2026-08-15). Data as JSON: /api/errors/716979266ff52b74. Report an issue: GitHub.