JuliusBrussee/caveman · error · Error

cave_execution_authorization_private

Error message

cave_execution_authorization_private

What it means

rejectInternalOptions() guards the public Claude run options: lockedBuild, candidatePlan, and queryFn are internal fields reserved for the framework's own build/execution pipeline (locked builds, candidate evaluation, recorded query injection). A public caller passing any of them is attempting to use private authorization-adjacent machinery, which is refused so callers cannot forge a locked-build execution or smuggle a fake query stream.

Source

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

  // OAuth subscription runs still expose provider token counts, but catalog
  // list price is not money this run paid. Unknown auth also fails closed to
  // the honest zero rather than guessing a metered credential.
  return { ...usage, priced: false, catalogCostUsd: 0 };
}

function integer(value: unknown): number {
  return Number.isSafeInteger(value) && Number(value) >= 0 ? Number(value) : 0;
}

function unprefixClaudeTool(name: string): string {
  const prefix = "mcp__caveman_agent__";
  return name.startsWith(prefix) ? name.slice(prefix.length) : name;
}

function rejectInternalOptions(options: ClaudeRunOptions): void {
  const value = options as Record<string, unknown>;
  if ("lockedBuild" in value || "candidatePlan" in value || "queryFn" in value) {
    throw new Error("cave_execution_authorization_private");
  }
}

function isRecord(value: unknown): value is Record<string, unknown> {
  return value !== null && typeof value === "object" && !Array.isArray(value);
}

View on GitHub (pinned to 27d5a3981a)

Solutions

  1. Remove lockedBuild/candidatePlan/queryFn from the options you pass; construct a fresh public options object with only documented fields.
  2. If you genuinely need locked/candidate execution, go through the framework's build pipeline (caveman-agent build / dev), not the public run API.
  3. If a spread is pulling them in, destructure them out: const { lockedBuild, candidatePlan, queryFn, ...public } = internal;

Example fix

// before
await run({ prompt, queryFn: fakeQuery, maxBudgetUsd: 1 });

// after
await run({ prompt, maxBudgetUsd: 1 });
Defensive patterns

Strategy: validation

Validate before calling

const INTERNAL_OPTION_KEYS = ["lockedBuild", "candidatePlan", "queryFn"] as const;
function assertPublicOptions(options: Record<string, unknown>): void {
  for (const key of INTERNAL_OPTION_KEYS) {
    if (key in options) throw new Error(`option '${key}' is framework-internal`);
  }
}

Type guard

function isPublicRunOptions(value: unknown): value is ClaudeRunOptions {
  if (typeof value !== "object" || value === null) return false;
  const keys = Object.keys(value);
  return !keys.includes("lockedBuild") && !keys.includes("candidatePlan") && !keys.includes("queryFn");
}

Prevention

When it happens

Trigger: Calling the public run API with an options object that includes lockedBuild, candidatePlan, or queryFn — even set to undefined via spread from an internal type, or copied from framework-internal code into application code.

Common situations: Copy-pasting example code from the framework's internal executor into an app; using `as any` to satisfy a type error by passing internal fields; structurally cloning an internal run options object and handing it to the public entry point.

Related errors


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