JuliusBrussee/caveman · error · Error

${where} manifestation node ${slice.manifestation_node_id} i

Error message

${where} manifestation node ${slice.manifestation_node_id} is not a node of variant ${sliceVariant.id}

What it means

When causal_slice.manifestation_node_id is non-empty it must be a node of the slice variant — an id in sliceVariant.nodes (validate-continuous-improvement.mjs:175-178). The empty string is the allowed 'no manifestation pinned' sentinel and is skipped; any other id must exist among that variant's nodes.

Source

Thrown at packages/shared/contracts/scripts/validate-continuous-improvement.mjs:177

    for (const trace of item.representative_traces) {
      const variant = armVariants.get(trace.arm);
      if (!variant || variant.id !== trace.variant_id) throw new Error(`${where} representative trace names a variant that is not that arm's variant`);
      if (!unitsByID.has(trace.analysis_unit_id)) throw new Error(`${where} representative trace ${trace.analysis_unit_id} is not an analysis unit of this report`);
      if (!familyUnits.has(trace.analysis_unit_id)) throw new Error(`${where} representative trace ${trace.analysis_unit_id} is not a member of the cohort's task family`);
      if (!variant.analysis_unit_ids.includes(trace.analysis_unit_id)) throw new Error(`${where} representative trace ${trace.analysis_unit_id} did not run that arm's workflow variant`);
      selectedPerArm.set(trace.arm, (selectedPerArm.get(trace.arm) ?? 0) + 1);
    }
    for (const [arm, count] of selectedPerArm) {
      if (count > 3) throw new Error(`${where} arm ${arm} carries ${count} representative traces, more than three`);
    }

    const slice = item.causal_slice;
    const sliceVariant = variantsByID.get(slice.variant_id);
    if (!sliceVariant) throw new Error(`${where} causal slice references a workflow variant that is not in this report`);
    if (sliceVariant.id !== armVariants.get("baseline").id) throw new Error(`${where} causal slice is not taken from the baseline arm's variant`);
    const sliceNodes = new Set(sliceVariant.nodes.map((node) => node.id));
    if (slice.manifestation_node_id !== "" && !sliceNodes.has(slice.manifestation_node_id)) {
      throw new Error(`${where} manifestation node ${slice.manifestation_node_id} is not a node of variant ${sliceVariant.id}`);
    }
    if (item.diagnosis.manifestation.node_id !== slice.manifestation_node_id) {
      throw new Error(`${where} diagnosis manifestation node disagrees with its causal slice`);
    }
    for (const nodeID of slice.node_chain) {
      if (!sliceNodes.has(nodeID)) throw new Error(`${where} causal slice node ${nodeID} is not a node of variant ${sliceVariant.id}`);
    }
    if (slice.manifestation_node_id !== "" && !slice.node_chain.includes(slice.manifestation_node_id)) {
      throw new Error(`${where} causal slice omits its own manifestation node`);
    }
    const provenDependency = (edge) => edge.strength === "hard" && (edge.type === "data" || edge.type === "control") && edge.evidence_refs.length > 0;
    const variantEdges = new Map(sliceVariant.edges.map((edge) => [`${edge.from}${edge.to}${edge.type}`, edge]));
    for (const edge of slice.hard_edges) {
      if (!provenDependency(edge)) throw new Error(`${where} hard chain carries an unproven edge ${edge.from}->${edge.to}`);
      if (!sliceNodes.has(edge.from) || !sliceNodes.has(edge.to)) throw new Error(`${where} hard chain edge ${edge.from}->${edge.to} names a node outside variant ${sliceVariant.id}`);
      if (!slice.node_chain.includes(edge.from) || !slice.node_chain.includes(edge.to)) {
        throw new Error(`${where} hard chain edge ${edge.from}->${edge.to} is outside the slice's node chain`);
      }

View on GitHub (pinned to 766dce6b13)

Solutions

  1. Set manifestation_node_id to an existing node id of the baseline variant.
  2. If no manifestation node should be asserted, use "" — and make diagnosis.manifestation.node_id "" too (error 616).
  3. Re-run the validator.

Example fix

// before — variant nodes are [node/parse, node/exec]
"manifestation_node_id": "node/exec-plan"
// after
"manifestation_node_id": "node/exec"
Defensive patterns

Strategy: validation

Validate before calling

const danglingManifestationNodes = (report) => {
  const byID = new Map(report.workflow_variants.map((v) => [v.id, v]));
  return report.cases.filter((c) => {
    const nodes = new Set(byID.get(c.causal_slice.variant_id)?.nodes.map((n) => n.id) ?? []);
    return c.causal_slice.manifestation_node_id !== '' && !nodes.has(c.causal_slice.manifestation_node_id);
  }).map((c) => c.id);
};

Try / catch

try {
  execFileSync(process.execPath, [VALIDATOR, reportPath, spansPath]);
} catch (err) {
  if (/manifestation node .* is not a node/.test(err.message)) {
    failCI(`manifestation node not in the slice variant's node set: ${err.message}`);
  } else throw err;
}

Prevention

When it happens

Trigger: The node was renamed or removed from the variant's nodes array; the node id was copied from a different variant's node set; the id has a wrong prefix (node/exec-plan vs node/exec).

Common situations: Renaming node ids in a refactor; hand-authoring a slice against a mental model of the graph instead of the fixture's nodes list; sentinel misuse — writing a placeholder id instead of "".

Related errors


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