JuliusBrussee/caveman · error

cave_unknown_transform:${route.transform_id}

Error message

cave_unknown_transform:${route.transform_id}

What it means

Thrown while applying a plan when a segment_route references a transform_id outside the built-in known set (caveman.engine.{a11y,code,config,diff,html,json,log,repetition,search-result,tabular,terminal,text,toolschema,toon}.v1). Unknown transform engines are rejected before touching any segment.

Source

Thrown at packages/agent/src/runtime.ts:2631

      failures: [],
      recoveryResolved: true,
      recoveryHandles: new Set(),
      trace: [],
    };
  }
  const known = new Set([
    "a11y", "code", "config", "diff", "html", "json", "log", "repetition",
    "search-result", "tabular", "terminal", "text", "toolschema", "toon",
  ].map((name) => `caveman.engine.${name}.v1`));
  const evaluated: string[] = [];
  const applied: string[] = [];
  const failures: string[] = [];
  const handles = new Set<string>();
  const trace: MutableTransformTrace[] = [];
  let recoveryResolved = true;
  for (const route of plan.segment_routes) {
    if (!known.has(route.transform_id)) {
      throw new Error(`cave_unknown_transform:${route.transform_id}`);
    }
    const targets = lowered.ir.segments.filter((segment) =>
      segment.kind === route.segment_kind &&
      (route.segment_id === undefined || segment.id === route.segment_id));
    if (targets.length === 0) {
      if (route.segment_kind === "history" || route.segment_kind === "tool_result") {
        continue;
      }
      throw new Error(`cave_plan_route_unmatched:${route.segment_id ?? route.segment_kind}`);
    }
    evaluated.push(route.transform_id);
    let routeApplied = false;
    for (const segment of targets) {
      const original = lowered.bodies.get(segment.bodyHandle);
      if (!original) throw new Error(`cave_context_body_missing:${segment.id}`);
      if (segment.safety !== "S4") throw new Error(`cave_transform_safety_mismatch:${segment.id}`);
      const startedAt = performance.now();
      // beforeTokens/afterTokens are byte-derived (bytes/4) throughout so a

View on GitHub (pinned to 27d5a3981a)

Solutions

  1. Regenerate the plan with the same caveman version that executes it
  2. Check the transform_id in the error against the known list and fix typos/renames
  3. Pin matching versions of plan producer and runtime

Example fix

// before
const plan = { segment_routes: [{ transform_id: "caveman.engine.text.v2", segment_kind: "history" }] };

// after
const plan = { segment_routes: [{ transform_id: "caveman.engine.text.v1", segment_kind: "history" }] };
Defensive patterns

Strategy: validation

Validate before calling

const KNOWN = new Set([
  "a11y","code","config","diff","html","json","log","repetition",
  "search-result","tabular","terminal","text","toolschema","toon",
].map((n) => `caveman.engine.${n}.v1`));
function planTransformsKnown(plan: CavePlan): boolean {
  return plan.segment_routes.every((r) => KNOWN.has(r.transform_id));
}

Type guard

function unknownTransform(e: unknown): string | null {
  if (!(e instanceof Error)) return null;
  const m = /^cave_unknown_transform:(.+)$/.exec(e.message);
  return m ? m[1] : null;
}

Try / catch

if (!planTransformsKnown(plan)) {
  plan = await buildPlan(...); // regenerate with the current version
}
await applyPlan(plan, lowered);

Prevention

When it happens

Trigger: plan.segment_routes contains a transform_id not in the hardcoded set — e.g. a plan produced by a newer/older caveman version with different engine names, or a hand-written plan with a typo'd id.

Common situations: Version skew: plan serialized by one version of caveman, executed by another whose engine set differs; custom or experimental transform ids; typos when authoring plans by hand.

Related errors


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