affaan-m/ECC · error · ContractError
receipt reference digest has conflicting source durations
Error message
receipt reference digest has conflicting source durations
What it means
When two receipt references cite the same artifact digest (same sha256) but declare different source_duration values, the receipt is self-contradictory: the same file cannot have two durations. validate_bundle builds a digest→duration map and raises this ContractError on the first conflict, protecting downstream recipe validation that relies on consistent durations.
Solutions
- Regenerate the receipt with the standard pipeline so duplicates share one consistent duration
- Make all references with the same sha256 carry the identical source_duration value
- Remove duplicate/stale reference entries for the same digest
- Restore the receipt from a single coherent run rather than merging receipts
Example fix
// before: same digest, conflicting durations
[{"sha256": "abc", "source_duration": 12.5}, {"sha256": "abc", "source_duration": 13.0}]
// after
[{"sha256": "abc", "source_duration": 12.5}, {"sha256": "abc", "source_duration": 12.5}] Defensive patterns
Strategy: validation
Validate before calling
import json
def durations_consistent(receipt: dict) -> bool:
seen = {}
for ref in receipt.get("references", []):
digest, dur = ref.get("sha256"), ref.get("source_duration")
if digest in seen and seen[digest] != dur:
return False
seen[digest] = dur
return True Type guard
def no_conflicting_durations(references: list) -> bool:
seen: dict = {}
for ref in references:
d = ref.get("sha256"); dur = ref.get("source_duration")
if d in seen and seen[d] != dur:
return False
seen[d] = dur
return True Try / catch
from tasteforge.contract import ContractError
try:
validate_bundle(out_dir)
except ContractError as e:
if "conflicting source durations" in str(e):
regenerate_bundle(out_dir) # merged/edited receipts are unusable Prevention
- Never merge receipts from separate runs
- Update all duplicate entries for a digest together if edits are unavoidable
- Derive duration per source file once and reuse it for all its references
When it happens
Trigger: A receipt whose references list contains the same sha256 twice with differing source_duration floats — e.g. merging receipts from two runs, editing one entry's duration, or a generator emitting duplicate references with stale durations.
Common situations: Manually merging or patching receipts, copy-paste edits to fix durations for one reference but not its duplicates, or custom tooling that re-derives durations per-clip instead of per-source-file.
Understand the failure class
Background: "This is a bug, please report it": internal invariant violations, unreachable panics, and SNH errors explained — this error's family across 47 libraries.
Related errors
- artifact byte size does not match receipt
- audit health evidence does not match its evaluation
- Local ingestion must have zero provider calls
- missing receipt
- receipt binds missing artifact
AI-assisted analysis of affaan-m/ECC@8321021c54 (2026-09-16).
Data as JSON: /api/errors/4d94f127ad1e38f6.
Report an issue: GitHub.
Appendix: source
Thrown at skills/taste-application/scripts/tasteforge/contract.py:478
raise ContractError("missing receipt")
receipt = json.loads(receipt_path.read_text(encoding="utf-8"))
if (receipt.get("dry_run") is not True
or receipt.get("provider_execution") is not False
or type(receipt.get("provider_calls")) is not int
or receipt.get("provider_calls") != 0):
raise ContractError("receipt crosses the dry-run boundary")
validate_artifact_receipt(out_dir, receipt)
reference_durations: dict[str, float] = {}
for reference in receipt.get("references", []):
digest = reference.get("sha256")
duration = reference.get("source_duration")
if not isinstance(digest, str) or not _is_finite_real(duration):
raise ContractError("receipt reference cannot bind recipe evidence")
duration = float(duration)
previous = reference_durations.get(digest)
if previous is not None and previous != duration:
raise ContractError("receipt reference digest has conflicting source durations")
reference_durations[digest] = duration
recipe_path = out_dir / "resolve" / "effect_recipe.json"
if not recipe_path.is_file():
raise ContractError("missing Resolve effect recipe")
validate_effect_recipe(
json.loads(recipe_path.read_text(encoding="utf-8")),
reference_durations=reference_durations,
)
View on GitHub (pinned to 8321021c54)