JuliusBrussee/caveman · error · Error
references a task family that is not in this report
Error message
${where} references a task family that is not in this report What it means
Every motif must reference a task family that exists in the same report fixture. The validator builds a set of task_families ids and throws when a motif's task_family_id is absent, enforcing referential integrity inside each report.
Solutions
- Correct the motif's task_family_id to match an existing task_families[].id in the same report.
- If the family was renamed, update all motifs referencing the old id.
- Add the missing task family entry to task_families if it legitimately should exist.
Example fix
// before
{ "motifs": [{ "id": "m1", "task_family_id": "family-old" }] }
// after
{ "motifs": [{ "id": "m1", "task_family_id": "family-renamed" }] } Defensive patterns
Strategy: validation
Validate before calling
const familyIDs = new Set(report.task_families.map(f => f.id));
for (const m of report.motifs) if (!familyIDs.has(m.task_family_id)) throw new Error(`motif ${m.id}: unknown task_family_id ${m.task_family_id}`); Type guard
const motifFamilyExists = (motif, report) => report.task_families.some(f => f.id === motif.task_family_id);
Try / catch
try { validateContinuousImprovement(report); } catch (e) { if (String(e.message).includes('references a task family')) { console.error('Update motif.task_family_id to a family present in this report'); } else throw e; } Prevention
- Generate motifs from the same report's task_families, never copy across reports
- Grep fixtures for renamed family ids after refactors
- Enforce referential integrity in the fixture generator itself
When it happens
Trigger: A report's motifs[] entry has task_family_id that does not match any id in that report's task_families[] (typo, renamed family, or motif copied from another report).
Common situations: Renaming a task family id in fixtures without updating motifs; duplicating a motif across report fixtures with different family ids; typos in hand-authored fixtures.
Understand the failure class
Background: "Not found" and "does not exist" errors: why "Task not found", "No such folder", and "Can't find" fire when a lookup comes back empty — this error's family across 14 libraries.
Related errors
- references workflow variant that is not in this report
- supporting variant belongs to another task family
- carries more shared unit ids than its shared unit count
- causal slice references a workflow variant that is not in…
- operations are not a contiguous subsequence of variant 's…
AI-assisted analysis of JuliusBrussee/caveman@3ee70a1026 (2026-09-20).
Data as JSON: /api/errors/53c324cd0d3320d9.
Report an issue: GitHub.
Appendix: source
Thrown at packages/shared/contracts/scripts/validate-continuous-improvement.mjs:110
}
const expectedBGivenA = relationship.shared_unit_count / relationship.theme_a_unit_count;
const expectedAGivenB = relationship.shared_unit_count / relationship.theme_b_unit_count;
if (Math.abs(relationship.probability_b_given_a - expectedBGivenA) > 1e-9) {
throw new Error(`${where} probability_b_given_a ${relationship.probability_b_given_a} != ${expectedBGivenA}`);
}
if (Math.abs(relationship.probability_a_given_b - expectedAGivenB) > 1e-9) {
throw new Error(`${where} probability_a_given_b ${relationship.probability_a_given_b} != ${expectedAGivenB}`);
}
}
relationshipCount += report.relationships.length;
// A motif is a structural count over variants this report carries, so every
// part of it must be re-derivable from those variants.
const variantsByID = new Map(report.workflow_variants.map((variant) => [variant.id, variant]));
const familyIDs = new Set(report.task_families.map((family) => family.id));
for (const motif of report.motifs) {
const where = `report fixture ${reportPaths[index]}: motif ${motif.id}`;
if (!familyIDs.has(motif.task_family_id)) throw new Error(`${where} references a task family that is not in this report`);
if (motif.support_variant_count !== motif.variant_ids.length) throw new Error(`${where} support variant count disagrees with its variant ids`);
let runs = 0;
let weighted = 0;
for (const variantID of motif.variant_ids) {
const variant = variantsByID.get(variantID);
if (!variant) throw new Error(`${where} references workflow variant ${variantID} that is not in this report`);
if (variant.task_family_id !== motif.task_family_id) throw new Error(`${where} supporting variant ${variantID} belongs to another task family`);
if (!contiguouslyContains(variant.signature, motif.operations)) {
throw new Error(`${where} operations are not a contiguous subsequence of variant ${variantID}'s signature`);
}
runs += variant.eligible_runs;
weighted += (motif.operations.length / variant.signature.length) * variant.eligible_runs;
}
if (motif.support_run_count !== runs) throw new Error(`${where} support run count ${motif.support_run_count} != ${runs}`);
const expectedShare = runs > 0 ? weighted / runs : 0;
if (Math.abs(motif.structural_cost_share - expectedShare) > 1e-6) {
throw new Error(`${where} structural_cost_share ${motif.structural_cost_share} != ${expectedShare}`);
}View on GitHub (pinned to 3ee70a1026)