affaan-m/ECC · error · ValueError
approval evidence must bind exact source, candidate and…
Error message
approval evidence must bind exact source, candidate and placement
What it means
_inserts validates that the approval file evidence for each insert cryptographically binds the exact candidate media, the exact source media, the compiled input digest, the edit-context digest, and the exact source and timeline ranges. Any missing, extra, or non-matching field in the approval JSON means the approval cannot be proven to refer to this exact placement, so bundling is refused.
Solutions
- Regenerate the approval file so its fields are computed from the current candidate, source, compiled input, and ranges
- Ensure the approval file contains every expected key with status 'approved','candidate_sha256','source_sha256','compiled_input_sha256','edit_context_sha256','candidate_range','timeline_range'
- Re-run the approval step after any change to the compiled input or edit context so the digests refresh
- If ranges changed, capture a new approval for the new placement instead of hand-editing the old evidence
Example fix
// before (stale approval)
{"status": "approved", "candidate_sha256": "aaa..."}
// after (fully bound)
{"status": "approved", "candidate_sha256": "<candidate sha>", "source_sha256": "<source sha>", "compiled_input_sha256": "<input hash>", "edit_context_sha256": "<edit hash>", "candidate_range": [0, 48], "timeline_range": [120, 168]} Defensive patterns
Strategy: validation
Validate before calling
import json
def approval_is_current(evidence, expected):
if not isinstance(evidence, dict):
return False
return all(json.dumps(evidence.get(k), sort_keys=True) == json.dumps(v, sort_keys=True)
for k, v in expected.items()) Type guard
def is_bound_approval(e):
return isinstance(e, dict) and all(k in e for k in ("status","candidate_sha256","source_sha256","compiled_input_sha256","edit_context_sha256","candidate_range","timeline_range")) Try / catch
try:
bundle = build_application_bundle(cfg, ci)
except ValueError as e:
if "approval evidence must bind" in str(e):
recapture_approvals(cfg) # regenerate approval files from current inputs
else:
raise Prevention
- Always recapture approval evidence after any edit to compiled input or timeline
- Never hand-edit approval JSON files
- Include all seven binding fields when generating approvals
- Store approvals per-candidate-id to avoid cross-candidate reuse
When it happens
Trigger: build_application_bundle reads item['approval_file'] via _artifact(parse_json=True) and compares it canonically against the expected dict {status:approved, candidate_sha256, source_sha256, compiled_input_sha256, edit_context_sha256, candidate_range, timeline_range}; any key whose canonical JSON differs, or a non-dict evidence file, triggers the error.
Common situations: Editing the timeline after approval was captured (ranges no longer match); rebuilding the compiled input so input_hash changed; reusing an approval file from a different candidate; hand-written approval JSON missing a required key or with floats formatted differently.
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
- application bundle differs from its bound evidence
- artifact byte size does not match receipt
- artifact cites an unknown provenance source
- effect evidence source duration is not bound to its receipt…
- every original audio clip must be preserved exactly once
AI-assisted analysis of affaan-m/ECC@8321021c54 (2026-09-16).
Data as JSON: /api/errors/299d445026dc6607.
Report an issue: GitHub.
Appendix: source
Thrown at skills/taste-application/scripts/tasteforge/integration.py:334
raise ValueError("insert requires an approved, resolved candidate")
target = _range(item["timeline_range"], config["baseline"]["timeline_range"])
source = _range(item["candidate_range"], [0, candidate["media_frames"]])
if any(_overlap(target, p["range"]) for p in config["protected_intervals"]):
raise ValueError("insert overlaps protected original stack")
if any(_overlap(target, span) for span in occupied):
raise ValueError("insert proposals overlap")
if (item["retime"] != "none" or target[1] - target[0] != source[1] - source[0]
or _rate(candidate["fps"]) != _rate(config["baseline"]["fps"])):
raise ValueError("candidate fps/duration/retime ambiguity")
evidence = _artifact(item["approval_file"], parse_json=True)
expected = {"status": "approved", "candidate_sha256": candidate["media"]["sha256"],
"source_sha256": config["source"]["media"]["sha256"],
"compiled_input_sha256": input_hash,
"edit_context_sha256": edit_hash,
"candidate_range": source, "timeline_range": target}
if not isinstance(evidence, dict) or any(
_canonical(evidence.get(key)) != _canonical(value) for key, value in expected.items()):
raise ValueError("approval evidence must bind exact source, candidate and placement")
occupied.append(target)
def build_application_bundle(config: dict, compiled_input: dict | None, *, local_only: bool = False) -> dict:
"""Validate resident evidence and return a new deterministic, offline bundle."""
if type(local_only) is not bool:
raise ValueError("local_only must be an exact boolean")
_object(config, _REQUIRED, _OPTIONAL)
if len(_canonical(config)) > _MAX_JSON:
raise ValueError("application config exceeds local size limit")
if local_only:
if compiled_input is not None:
raise ValueError("local-only preservation cannot accept provider input")
else:
_object(compiled_input, {"source_video", "compiled_prompt"})
url = urlsplit(_text(compiled_input["source_video"]))
if url.scheme != "https" or not url.hostname or url.username or url.password:
raise ValueError("source reference must be HTTPS without embedded credentials")View on GitHub (pinned to 8321021c54)