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

  1. Set item['retime'] to 'none' in the insert entry, or drop the retime field entirely
  2. Adjust the insert's timeline_range so its duration exactly equals the source candidate_range duration
  3. Re-encode or re-export the candidate at the baseline project fps so _rate(candidate.fps) == _rate(baseline.fps)
  4. 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

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


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)