affaan-m/ECC · error · ValueError
candidate fps/duration/retime ambiguity
Error message
candidate fps/duration/retime ambiguity
What it means
In tasteforge's _inserts, each approved insert proposal must be a straight passthrough of the candidate: same fps as the project baseline, identical duration in source and timeline ranges, and retime mode 'none'. If any of these differ, the tool cannot place the insert without transcoding or retiming, so it raises this error to force an explicit decision.
Solutions
- Set item['retime'] to 'none' in the insert entry, or drop the retime field entirely
- Adjust the insert's timeline_range so its duration exactly equals the source candidate_range duration
- Re-encode or re-export the candidate at the baseline project fps so _rate(candidate.fps) == _rate(baseline.fps)
- Move the insert to a separate retime workflow step instead of bundling it as a passthrough insert
Example fix
// before
{"id": "ins1", "candidate": "c1", "range": [0, 48], "timeline_range": [120, 121], "retime": "linear"}
// after
{"id": "ins1", "candidate": "c1", "range": [0, 48], "timeline_range": [120, 168], "retime": "none"} Defensive patterns
Strategy: validation
Validate before calling
def insert_is_passthrough(item, candidate, baseline):
return (item.get("retime", "none") == "none"
and item["timeline_range"][1] - item["timeline_range"][0] == item["range"][1] - item["range"][0]
and float(candidate["fps"]) == float(baseline["fps"])) Type guard
def is_valid_insert(item):
return isinstance(item, dict) and item.get("retime") == "none" and isinstance(item.get("range"), list) and isinstance(item.get("timeline_range"), list) Try / catch
try:
bundle = build_application_bundle(cfg, ci)
except ValueError as e:
if "fps/duration/retime" in str(e):
fix_insert_to_passthrough(cfg) # set retime='none' and equalize durations
else:
raise Prevention
- Always export candidates at the baseline project fps
- Enforce retime='none' at config-authoring time with a lint/schema check
- Assert range lengths match timeline_range lengths before building
- Keep retimed edits in a separate workflow from passthrough inserts
When it happens
Trigger: Calling build_application_bundle with a config whose inserts[] item has retime != 'none', a timeline_range whose length differs from its candidate_range length, or a candidate whose fps differs from config['baseline']['fps'] (compared via _rate, so e.g. 30 vs 29.97 also fails).
Common situations: Hand-authored or regenerated candidate configs where fps metadata drifted from the baseline (mixed-frame-rate stock footage); edited ranges that were stretched or trimmed during timeline edits; leftover retime fields from a previous slow-motion proposal that was approved without being reverted.
Understand the failure class
Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.
Related errors
- apply_local needs at least one media clip
- asset contains too few frames
- asset requires verified alpha
- Crop must contain four finite values
- FileNotFoundError(source)
AI-assisted analysis of affaan-m/ECC@8321021c54 (2026-09-16).
Data as JSON: /api/errors/089518ccf9956340.
Report an issue: GitHub.
Appendix: source
Thrown at skills/taste-application/scripts/tasteforge/integration.py:325
return result
def _inserts(items: list, candidates: dict, config: dict, input_hash: str, edit_hash: str) -> None:
occupied = []
for item in items:
_object(item, {"candidate_id", "candidate_range", "timeline_range", "retime", "approval_file"})
candidate = candidates.get(_text(item["candidate_id"]))
if candidate is None or candidate["review_status"] != "approved":
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:View on GitHub (pinned to 8321021c54)