JuliusBrussee/caveman · error

cave_unknown_transform

cave_unknown_transform

Error message

cave_unknown_transform:${route.transform_id}

What it means

Thrown when a compaction plan's segment_routes reference a transform_id that is not in the set of known/registered transforms. The runtime validates every route's transform before evaluating routes and fails fast on unknown ids. This guards against plans naming transforms that were never registered with the engine.

Solutions

  1. Print the registered transform set and correct the plan's transform_id to an existing one.
  2. Register the missing transform with the engine before executing the plan.
  3. Regenerate the plan with the current runtime version instead of reusing a stale one.
  4. Fix typos in the transform_id — engine ids follow the caveman.engine.<slug>.v1 pattern.

Example fix

// before
segment_routes: [{ segment_kind: "history", transform_id: "caveman.engine.summarize.v2" }]
// after
segment_routes: [{ segment_kind: "history", transform_id: "caveman.engine.summarize.v1" }]
Defensive patterns

Strategy: validation

Validate before calling

const known = new Set(registeredTransforms.map(t => t.id));
const bad = plan.segment_routes.filter(r => !known.has(r.transform_id));
if (bad.length) throw new Error(`unknown transforms in plan: ${bad.map(r => r.transform_id).join(",")}`);

Type guard

function isKnownTransform(id: string, known: Set<string>): boolean { return known.has(id); }

Try / catch

try {
  await executePlan(plan, lowered);
} catch (err) {
  if (err instanceof Error && err.message.startsWith("cave_unknown_transform:")) {
    const id = err.message.split(":")[1];
    // register the transform or regenerate the plan with valid ids
  } else throw err;
}

Prevention

When it happens

Trigger: Executing a plan whose plan.segment_routes[i].transform_id is not present in the known transform registry — e.g. a hand-written plan, a plan from an older/newer runtime version, or a typo in the transform id (engine transforms must match caveman.engine.<name>.v1).

Common situations: Plan files produced by a different engine version whose transform set changed; hand-authoring plans with invented transform names; registering transforms conditionally so the plan's transform wasn't registered this run.

Understand the failure class

Background: "invalid id" errors: invalid identifier format — why libraries reject IDs before lookup, and how to fix them — this error's family across 37 libraries.

Related errors


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

Appendix: 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 3ee70a1026)