JuliusBrussee/caveman · error · Error

cave_harness_unknown_transform

cave_harness_unknown_transform

Error message

cave_harness_unknown_transform

What it means

evaluatedTransformIDs and appliedTransformIDs may only contain transform IDs that the locked plan selected (plan.segment_routes[].transform_id). An ID absent from the selected set is an unauthorized claim of work the plan never approved, so the adapter throws cave_harness_unknown_transform.

Solutions

  1. Recompute both lists from the current plan's segment_routes instead of caching them
  2. Never merge transform evidence across runs or plans
  3. Validate both directions of the set comparison before run() (see defense below)

Example fix

// before
await adapter.run({ ...req, evaluatedTransformIDs: ["t1", "t9-old"] });

// after
const selected = [...new Set(plan.segment_routes.map((r) => r.transform_id))];
await adapter.run({ ...req, evaluatedTransformIDs: selected, appliedTransformIDs: selected });
Defensive patterns

Strategy: validation

Validate before calling

const selected = [...new Set(plan.segment_routes.map((r) => r.transform_id))];
const evaluated = [...new Set(request.evaluatedTransformIDs)];
const applied = [...new Set(request.appliedTransformIDs)];
const unknown = [...evaluated, ...applied].filter((id) => !selected.includes(id));
if (unknown.length > 0) {
  throw new Error(`transform IDs not in plan: ${unknown.join(", ")}`);
}

Try / catch

try {
  const result = await adapter.run(request);
} catch (error) {
  if (error instanceof Error && error.message === "cave_harness_unknown_transform") {
    // Evidence contains transform IDs the plan never selected — the lists
    // are stale (likely from another plan); recompute from the current plan.
  }
  throw error;
}

Prevention

When it happens

Trigger: adapter.run() where either list contains a stale transform ID from a different/older plan, or IDs concatenated from another run's evidence, while validateTransformEvidence's selected-set comparison finds extras.

Common situations: Caching or persisting transform-ID lists across plan rebuilds; merging evidence lists from parallel runs; renaming a transform so old IDs linger in config.

Related errors


AI-assisted analysis of JuliusBrussee/caveman@766dce6b13 (2026-08-18). Data as JSON: /api/errors/fef319c19a79b3f3. Report an issue: GitHub.

Appendix: source

Thrown at packages/agent/src/adapters.ts:680

  evidence: Pick<HarnessRequest, "evaluatedTransformIDs" | "appliedTransformIDs" | "recoveryResolved">,
  plan: CavePlan,
): void {
  if (!Array.isArray(evidence.evaluatedTransformIDs) ||
      !Array.isArray(evidence.appliedTransformIDs) ||
      evidence.evaluatedTransformIDs.some((value) => typeof value !== "string" || value.length === 0) ||
      evidence.appliedTransformIDs.some((value) => typeof value !== "string" || value.length === 0) ||
      evidence.recoveryResolved !== true) {
    throw new Error("cave_harness_incomplete_evidence");
  }
  const selected = [...new Set(plan.segment_routes.map((route) => route.transform_id))].sort();
  const evaluated = [...new Set(evidence.evaluatedTransformIDs)].sort();
  const applied = [...new Set(evidence.appliedTransformIDs)].sort();
  if (selected.some((transformID) => !evaluated.includes(transformID))) {
    throw new Error("cave_harness_transform_not_evaluated");
  }
  if (evaluated.some((transformID) => !selected.includes(transformID)) ||
      applied.some((transformID) => !selected.includes(transformID))) {
    throw new Error("cave_harness_unknown_transform");
  }
}

function validateExecution(execution: HarnessExecution, plan: CavePlan): void {
  const [provider, ...modelParts] = plan.model.split("/");
  const model = modelParts.join("/");
  try {
    validateProviderUsage(execution, {
      expected: { provider: provider ?? "", model },
      reportedCostUsd: execution.costUsd,
      requirePriced: true,
    });
  } catch {
    throw new Error("cave_harness_incomplete_evidence");
  }
  if (execution.terminal !== true || typeof execution.text !== "string" ||
      execution.text.length === 0 ||
      execution.usageBasis !== "provider_reported" ||

View on GitHub (pinned to 766dce6b13)