affaan-m/ECC · error · ValueError
cadence.json has no measured shots to plan from
Error message
cadence.json has no measured shots to plan from
What it means
apply_local validates that the loaded cadence.json is a dict containing either a 'shots' list or a 'mean_shot' entry. If the file exists but has neither (wrong shape, empty object, or non-dict like a list), planning shot durations is impossible, so it raises ValueError. This guards against corrupted or hand-edited cadence files.
Solutions
- Regenerate cadence.json with the pack's measurement pipeline so it contains 'shots' (or at least 'mean_shot').
- Inspect the JSON: it must be an object with a non-empty 'shots' list or a 'mean_shot' key.
- Fix hand-edited cadence.json to match the expected schema.
- Rebuild the style pack from source media if the cadence data is unrecoverable.
Example fix
// before
cadence.json -> {} // apply_local raises
cadence.json -> [] // apply_local raises
// after
cadence.json -> {"shots": [1.2, 0.8, 1.5], "fps": 24} Defensive patterns
Strategy: validation
Validate before calling
cad = json.loads(sp.cadence_path.read_text())
assert isinstance(cad, dict) and (cad.get("shots") or "mean_shot" in cad), "cadence.json invalid" Type guard
def is_valid_cadence(cad) -> bool:
return isinstance(cad, dict) and bool(cad.get("shots") or "mean_shot" in cad) Try / catch
try:
report = apply_local(sp, media=clips)
except ValueError as e:
if "no measured shots" in str(e):
regenerate_cadence(sp)
report = apply_local(sp, media=clips)
else:
raise Prevention
- Never hand-edit cadence.json; regenerate it with the measurement pipeline.
- Validate cadence.json against the expected schema after every build.
- Treat an empty shots list as a build failure in CI.
When it happens
Trigger: Calling apply_local(sp, ...) where sp.read_json(sp.cadence_path) returns an empty dict {}, a non-dict (list/str), or a dict lacking both 'shots' and 'mean_shot' keys.
Common situations: Manually creating a placeholder cadence.json that is empty or has the wrong schema; a cadence build step that produced no shots (e.g. empty input video set) and wrote an empty JSON object; a schema change between library versions.
Understand the failure class
Background: Schema validation failed / invalid input schema: payload rejected because its shape doesn't match the expected schema — this error's family across 28 libraries.
Related errors
- -32602
- apply_local produced an invalid report
- artifact path must be a non-empty relative path
- assets must be a nonempty list
- built an invalid spec
AI-assisted analysis of affaan-m/ECC@8321021c54 (2026-09-16).
Data as JSON: /api/errors/d6a0087fe6efe8d9.
Report an issue: GitHub.
Appendix: source
Thrown at skills/taste-application/scripts/tasteforge/apply.py:161
With ``no_repeat=True``, normalized source paths are used at most once;
insufficient sources or source durations fail instead of repeating clips.
Strict plans fill the nearest whole-frame target and never exceed source
capacity. Media duration metadata must describe the available source.
Returns an application report validated against
``schema.APPLICATION_REPORT_SCHEMA``. The report structurally cannot
claim a provider run: ``provider`` is enum-locked to ``"none"`` and
``dry_run`` to ``true``.
"""
if not media:
raise ValueError("apply_local needs at least one media clip")
if not sp.cadence_path.exists():
raise ValueError("pack has no measured cadence (cadence.json is missing)")
cadence = sp.read_json(sp.cadence_path)
if not isinstance(cadence, dict) or not (cadence.get("shots") or "mean_shot" in cadence):
raise ValueError("cadence.json has no measured shots to plan from")
seq_fps = _positive(fps if fps is not None else cadence.get("fps", _DEFAULT_FPS), "fps")
validated_media = []
for clip in media:
if not isinstance(clip, dict) or not isinstance(clip.get("path"), (str, Path)):
raise ValueError("media clips require a local source path")
if not str(clip["path"]).strip():
raise ValueError("media clips require a local source path")
validated_media.append({**clip, "duration": _positive(clip.get("duration"), "media duration")})
target = _positive(duration if duration is not None else sum(
c["duration"] for c in validated_media
), "target duration")
planned = plan_shots(cadence, target)
assignments = _strict_assign(planned, validated_media, target, seq_fps) if no_repeat else [
(validated_media[i % len(validated_media)], max(1, timeline.seconds_to_frames(d, seq_fps)))
for i, d in enumerate(planned)
]
shots: list[dict[str, Any]] = []View on GitHub (pinned to 8321021c54)