JuliusBrussee/caveman · error
cave_plan_route_unmatched:${route.segment_id ?? route.segmen
Error message
cave_plan_route_unmatched:${route.segment_id ?? route.segment_kind} What it means
Thrown when a plan route matches zero segments in the lowered IR. Routes targeting history or tool_result kinds are tolerated (they may legitimately match nothing and 'continue'), but any other unmatched route is an error: the plan does not correspond to this context.
Source
Thrown at packages/agent/src/runtime.ts:2640
].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
// delta is always within one basis. beforeTokens counts the ORIGINAL
// bytes; afterTokens, for an applied transform, counts the FULL provider
// body actually sent — wrapper included. segment.tokenCount
// is already estimateTokens(original) = bytes/4.
const beforeTokens = segment.tokenCount;
if (segment.opaque) {
trace.push({
segmentKind: segment.kind,
transformID: route.transform_id,View on GitHub (pinned to 27d5a3981a)
Solutions
- Regenerate the plan against the current lowered context
- If the id in the error message was renamed, update the plan to the new segment id
- Invalidate cached plans whenever the agent definition or contexts change
Defensive patterns
Strategy: validation
Validate before calling
function planRoutesMatch(plan: CavePlan, lowered: LoweredContext): boolean {
return plan.segment_routes.every((route) => {
const hits = lowered.ir.segments.filter((s) =>
s.kind === route.segment_kind &&
(route.segment_id === undefined || s.id === route.segment_id));
return hits.length > 0 || route.segment_kind === "history" || route.segment_kind === "tool_result";
});
} Type guard
function planRouteUnmatched(e: unknown): string | null {
if (!(e instanceof Error)) return null;
const m = /^cave_plan_route_unmatched:(.+)$/.exec(e.message);
return m ? m[1] : null;
} Try / catch
if (!planRoutesMatch(plan, lowered)) {
plan = await buildPlan(lowered); // plan and context must come from the same state
}
await applyPlan(plan, lowered); Prevention
- Never reuse a plan across definition or context revisions
- Regenerate plans in the same pipeline stage that lowers contexts
- Rename segment ids in plans and definitions together
When it happens
Trigger: A route's segment_kind/segment_id filter matches no segments — e.g. the plan was built for a different agent definition, a segment id was renamed, or the context composition changed after the plan was made. Only non-history, non-tool_result kinds throw.
Common situations: Reusing a cached plan across agent definitions or prompt revisions; renamed context segment ids; plan/context version skew.
Related errors
- cave_unknown_transform:${route.transform_id}
- cave_harness_model_invalid
- cave_harness_transform_not_evaluated
- cave_harness_unknown_transform
- cave_harness_plan_mismatch
AI-assisted analysis of JuliusBrussee/caveman@27d5a3981a (2026-08-15).
Data as JSON: /api/errors/443cfa15ce39ed43.
Report an issue: GitHub.