affaan-m/ECC · error · RetrospectiveError

retrospective.conflicting_identity

retrospective.conflicting_identity

Error message

conflicting snapshots share a capsule identity

What it means

Within one task family, each capsule identity (run_id + capsule_id) must be unambiguous: if two supplied capsules share the same identity but have different projection_hash values, they are conflicting snapshots of the same run and grouping them would silently mix inconsistent data. The library refuses at the index of the conflicting capsule. Identical duplicate snapshots (same identity and hash) are allowed and deduplicated.

Solutions

  1. Remove the older or conflicting snapshot so only one capsule per run_id/capsule_id remains
  2. Use distinct capsule IDs for separate checkpoints of the same run (the tool intentionally refuses ambiguous same-identity checkpoints)
  3. Regenerate the conflicting capsule if its contents were accidentally modified
  4. Deduplicate identical copies — equal hashes are fine and collapse automatically

Example fix

// before
node scripts/eval-harness.js capsule group ./run-7-snap1 ./run-7-snap2  // same id, different hashes
// after (keep one snapshot per capsule id)
node scripts/eval-harness.js capsule group ./run-7-snap2 ./run-8-snap1
Defensive patterns

Strategy: validation

Validate before calling

// detect duplicate capsule identities before grouping
const seen = new Map();
for (const d of dirs) { const id = readCapsuleIdentity(d); if (seen.has(id)) throw new Error(`duplicate capsule identity: ${id}`); seen.set(id, d); }

Try / catch

try { groupCapsules(dirs); } catch (e) { if (e.code === 'retrospective.conflicting_identity') console.error(`capsule #${e.index} conflicts with an earlier snapshot of the same run; keep one`); throw e; }

Prevention

When it happens

Trigger: Passing two different checkpoint snapshots of the same run/capsule (same run_id and capsule_id) whose contents diverged — e.g. capsule-a and capsule-a-rerun where the rerun produced different digests; a snapshot modified after the fact so its projection_hash no longer matches the earlier copy.

Common situations: Re-running a task and overwriting/regenerating a capsule with the same ID; including both pre-fix and post-fix snapshots of one run in the same group; sync tools restoring an older divergent copy alongside the new one.

Understand the failure class

Background: Conflicting config options: "cannot be used together" — configuration validation errors across open-source libraries — this error's family across 162 libraries.

Related errors


AI-assisted analysis of affaan-m/ECC@8321021c54 (2026-09-16). Data as JSON: /api/errors/d2cb3c8f4cebbe1d. Report an issue: GitHub.

Appendix: source

Thrown at scripts/lib/eval-harness/retrospective.js:79

 * Different checkpoints of the same identity are ambiguous and refused.
 * Does not read saved projections, copy payloads, write files or invoke tools.
 */
function groupCapsules(dirs) {
  if (!Array.isArray(dirs) || dirs.length < 1 || dirs.length > MAX_INPUTS
      || !Array.from(dirs).every(dir => typeof dir === 'string' && dir.trim() && !dir.includes('\0'))) {
    throw new RetrospectiveError('retrospective.invalid_inputs', `supply 1 to ${MAX_INPUTS} capsule directory paths`);
  }
  const projections = dirs.map(readProjection);
  const family = projections[0].task_family;
  const unique = new Map();
  for (const [index, projection] of projections.entries()) {
    if (projection.task_family !== family) {
      throw new RetrospectiveError('retrospective.mixed_task_families', 'all capsules must have the same task family', index);
    }
    const key = identity(projection);
    const previous = unique.get(key);
    if (previous && previous.projection_hash !== projection.projection_hash) {
      throw new RetrospectiveError('retrospective.conflicting_identity', 'conflicting snapshots share a capsule identity', index);
    }
    unique.set(key, projection);
  }
  const byHarness = new Map();
  for (const projection of unique.values()) {
    const version = projection.harness_version;
    byHarness.set(version, [...(byHarness.get(version) || []), projection]);
  }
  const report = {
    schema: 'capsule-retrospective/v1',
    report_only: true,
    task_family: family,
    input_count: dirs.length,
    capsule_count: unique.size,
    duplicate_count: dirs.length - unique.size,
    groups: [...byHarness].sort(([a], [b]) => compare(a, b))
      .map(([version, items]) => summarizeGroup(version, items)),
  };

View on GitHub (pinned to 8321021c54)