affaan-m/ECC · error · ContractError

effect evidence source duration is not bound to its receipt…

Error message

effect evidence source duration is not bound to its receipt reference

What it means

When reference_durations is supplied, each event's evidence must be bound to a known reference: evidence['reference_sha256'] must exist in the reference_durations map, and evidence['source_duration'] must exactly equal the duration recorded for that digest. This proves the effect was applied to the exact source media named by its receipt.

Solutions

  1. Recompute evidence from the correct reference media so reference_sha256 and source_duration match the receipt map.
  2. Update reference_durations (or pick the right receipt) so the digest is present and its duration matches.
  3. Compare durations with exact equality against the receipt; avoid reformatting source_duration (e.g. 10 vs 10.0 keys are fine, but '10.0' string is not).

Example fix

# before
evidence = {"reference_sha256": "deadbeef", "source_duration": 12.0}  # map says 10.0
# after
evidence = {"reference_sha256": digest_of_actual_source, "source_duration": reference_durations[digest_of_actual_source]}
Defensive patterns

Strategy: validation

Validate before calling

digest = ev["evidence"].get("reference_sha256")
expected = reference_durations.get(digest) if isinstance(digest, str) else None
if expected is None or ev["evidence"].get("source_duration") != expected:
    raise ValueError(f"evidence not bound to receipt for digest {digest}")

Type guard

def evidence_bound(ev: dict, reference_durations: dict) -> bool:
    digest = ev["evidence"].get("reference_sha256")
    expected = reference_durations.get(digest) if isinstance(digest, str) else None
    return expected is not None and ev["evidence"].get("source_duration") == expected

Try / catch

try:
    validate_effect_recipe(recipe, reference_durations=reference_durations)
except ContractError as exc:
    if "not bound to its receipt reference" in str(exc):
        recipe = rebind_evidence_to_receipts(recipe, reference_durations)
        validate_effect_recipe(recipe, reference_durations=reference_durations)
    else:
        raise

Prevention

When it happens

Trigger: validate_effect_recipe called with reference_durations where an event's evidence has a reference_sha256 absent from the map, a missing/non-string digest, or a source_duration that differs (even slightly) from the recorded value.

Common situations: Stale evidence pointing at re-encoded media whose duration changed; digest computed over the wrong file; copying evidence between events referencing different sources; float precision changes from JSON round-trips of source_duration.

Understand the failure class

Background: Checksum mismatch errors: "checksum verification failed", "digest mismatch", "expected vs actual checksum" — what they mean and how to fix them — this error's family across 41 libraries.

Related errors


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

Appendix: source

Thrown at skills/taste-application/scripts/tasteforge/contract.py:215

        duration = event.get("duration")
        if (not _is_finite_real(start) or not _is_finite_real(duration)
                or float(start) < 0 or float(duration) <= 0):
            raise ContractError("effect event start and duration must be finite positive timeline values")
        start = cast(float, start)
        duration = cast(float, duration)
        if float(start) + float(duration) > float(timeline) + 1e-9:
            raise ContractError("effect event end exceeds the declared timeline")
        evidence = event.get("evidence")
        if not isinstance(evidence, dict):
            raise ContractError(f"effect {event.get('effect')} lacks reference evidence")
        _validate_media_time(
            evidence.get("time"), evidence.get("source_duration"), label="effect evidence time"
        )
        if reference_durations is not None:
            digest = evidence.get("reference_sha256")
            expected_duration = reference_durations.get(digest) if isinstance(digest, str) else None
            if expected_duration is None or evidence.get("source_duration") != expected_duration:
                raise ContractError("effect evidence source duration is not bound to its receipt reference")
    times = [float(event["time"]) for event in events]
    if times != sorted(times) or len(times) != len(set(times)):
        raise ContractError("effect event times must be unique and increasing")
    intervals = [round(b - a, 6) for a, b in zip(times, times[1:])]  # noqa: RUF007
    if len(set(intervals)) <= 1:
        raise ContractError("stochastic schedule is periodic; intervals must vary")
    for period in range(1, len(intervals) // 2 + 1):
        if all(intervals[index] == intervals[index % period] for index in range(len(intervals))):
            raise ContractError("stochastic schedule is periodic; repeating interval cycle")
    if recipe.get("periodic") is not False:
        raise ContractError("effect recipe must explicitly declare periodic=false")
    for event in events:
        cv_effect = str(event.get("effect", "")).startswith("cv_")
        if cv_effect and event.get("requires_subject_anchor") is not True:
            raise ContractError(f"CV effect {event.get('effect')} must require a subject anchor")
        if event.get("requires_subject_anchor"):
            anchor = event.get("subject_anchor")
            required = {

View on GitHub (pinned to 8321021c54)