affaan-m/ECC · error · ValueError
native fps missing
Error message
native fps missing
What it means
_snapshot reads settings.timelineFrameRate from the native snapshot and requires it to be a string, int or float. If settings is missing, not a dict, or timelineFrameRate is absent/null/bool, the library raises "native fps missing" (immediately wrapped into the composite fps error).
Solutions
- Add or restore `"settings": {"timelineFrameRate": <rate>}` in the snapshot JSON, using the same label Resolve exports (e.g. "23.976", "24", or "24000/1001").
- Re-export the snapshot from the correct Resolve version so settings.timelineFrameRate is present.
- Check the key spelling/casing — it must be exactly `timelineFrameRate`.
- Make sure the value is a plain string/number, not null, true/false, or an object.
Example fix
// before
{"project": "P", "timeline": "T"}
// after
{"project": "P", "timeline": "T", "settings": {"timelineFrameRate": "23.976"}} Defensive patterns
Strategy: validation
Validate before calling
def has_native_fps(snapshot):
settings = snapshot.get("settings")
return isinstance(settings, dict) and type(settings.get("timelineFrameRate")) in (str, int, float) Type guard
def has_fps(snapshot) -> bool:
s = snapshot.get("settings") if isinstance(snapshot, dict) else None
return isinstance(s, dict) and type(s.get("timelineFrameRate")) in (str, int, float) Try / catch
try:
bundle = build_application_bundle(config, None, local_only=True)
except ValueError as exc:
if "fps is missing, invalid or contradictory" in str(exc):
print("snapshot settings.timelineFrameRate missing or wrong type")
raise Prevention
- Never strip the settings block from snapshots.
- Assert timelineFrameRate exists in export tests.
- Use exact Resolve export output without hand edits.
- Check key casing (timelineFrameRate) in the exporter.
When it happens
Trigger: build_application_bundle where the snapshot JSON lacks a `settings` object, or settings exists but has no `timelineFrameRate` key, or its value is null/bool/list/dict.
Common situations: Snapshot exported from a different tool that uses a different key name (e.g. frameRate, fps); an older Resolve version with a different settings layout; a hand-trimmed snapshot where the settings block was deleted.
Understand the failure class
Background: "is required", "must be set", "missing required field": configuration validation errors across open-source libraries — this error's family across 36 libraries.
Related errors
- native snapshot fps is missing, invalid or contradictory
- candidate fps/duration/retime ambiguity
- fps must be a reduced positive rational
- fps must be finite and positive
- fps must be finite and positive
AI-assisted analysis of affaan-m/ECC@8321021c54 (2026-09-16).
Data as JSON: /api/errors/c903d55dcec28358.
Report an issue: GitHub.
Appendix: source
Thrown at skills/taste-application/scripts/tasteforge/integration.py:202
raise ValueError("invalid JSON artifact") from exc
def _snapshot(baseline: dict) -> dict:
_object(baseline, {"project_file", "snapshot_file", "project_name", "timeline_name",
"fps", "timeline_range"})
_rate(baseline["fps"])
bounds = _range(baseline["timeline_range"])
_artifact(baseline["project_file"])
snapshot = _artifact(baseline["snapshot_file"], parse_json=True)
if not isinstance(snapshot, dict):
raise ValueError("native snapshot must be an object")
settings = snapshot.get("settings")
native_fps = settings.get("timelineFrameRate") if isinstance(settings, dict) else None
# Resolve's conventional decimal NTSC labels represent these exact rates.
ntsc = {"23.976": "24000/1001", "29.97": "30000/1001", "59.94": "60000/1001"}
try:
if type(native_fps) not in (str, int, float):
raise ValueError("native fps missing")
label = str(native_fps)
if not re.fullmatch(r"[0-9]{1,9}(?:\.[0-9]{1,12}|/[1-9][0-9]{0,8})?", label):
raise ValueError("native fps must use a bounded decimal or rational label")
native_rate = Fraction(ntsc.get(label, label))
if native_rate != Fraction(*_rate(baseline["fps"])):
raise ValueError("native fps differs")
except (ValueError, ZeroDivisionError) as exc:
raise ValueError("native snapshot fps is missing, invalid or contradictory") from exc
for cfg, key in [("project_name", "project"), ("timeline_name", "timeline")]:
if _text(baseline[cfg]) != snapshot.get(key):
raise ValueError("native snapshot identity mismatch")
tracks = snapshot.get("timeline_readback")
if not isinstance(tracks, dict) or not tracks:
raise ValueError("native clip snapshot required")
for track, clips in tracks.items():
if not re.fullmatch(r"(?:video|audio)[1-9][0-9]*", track) or not isinstance(clips, list):
raise ValueError("invalid native snapshot track")
for clip in clips:View on GitHub (pinned to 8321021c54)