affaan-m/ECC · error · ValueError
native snapshot must be an object
Error message
native snapshot must be an object
What it means
_snapshot validates the DaVinci Resolve native snapshot referenced by baseline.snapshot_file. After parsing it as JSON, it requires the top-level value to be a JSON object; arrays or scalars cannot carry settings/timeline_readback, so the library throws this error.
Solutions
- Point baseline.snapshot_file at the single-object snapshot export, not an array of snapshots.
- If you have an array, select the intended element and write it as the root object.
- Fix the exporter so it emits a single JSON object per snapshot file.
- Re-export the snapshot from Resolve and confirm the file starts with `{`.
Example fix
// before (snapshot.json)
[{"project": "P", "timeline": "T", ...}]
// after
{"project": "P", "timeline": "T", "settings": {...}, "timeline_readback": {...}} Defensive patterns
Strategy: validation
Validate before calling
import json
def check_snapshot_object(path):
snap = json.load(open(path, encoding="utf-8"))
if not isinstance(snap, dict):
raise TypeError(f"{path}: snapshot root must be an object")
if not isinstance(snap.get("settings"), dict) or "timelineFrameRate" not in snap["settings"]:
raise TypeError(f"{path}: missing settings.timelineFrameRate") Type guard
def is_snapshot(value) -> bool:
return isinstance(value, dict) and isinstance(value.get("settings"), dict) Try / catch
try:
bundle = build_application_bundle(config, None, local_only=True)
except ValueError as exc:
if "must be an object" in str(exc):
print("snapshot_file JSON root is not an object — re-export a single snapshot")
raise Prevention
- Export one snapshot per file, as a single JSON object.
- Validate snapshot shape right after export.
- Keep settings.timelineFrameRate intact when trimming snapshots.
- Pin snapshot files to the timeline they came from.
When it happens
Trigger: build_application_bundle -> _snapshot where snapshot_file's JSON parses successfully but its root is an array (e.g. a list of snapshots), a string, a number, or null.
Common situations: Exporting a batch of snapshots as a JSON array instead of one object; a snapshot exporter writing `null` when no timeline was open; wrapping the snapshot in an outer array during a migration.
Understand the failure class
Background: Type mismatch errors: IllegalArgumentException, TypeError and type guards across 150 open-source libraries — this error's family across 150 libraries.
Related errors
- application request must be a JSON object
- bundle values must be finite JSON data
- candidate configuration exceeds 1 MiB
- duplicate JSON field
- gate.taskset_invalid
AI-assisted analysis of affaan-m/ECC@8321021c54 (2026-09-16).
Data as JSON: /api/errors/a2560bad7778dc72.
Report an issue: GitHub.
Appendix: source
Thrown at skills/taste-application/scripts/tasteforge/integration.py:195
return result
try:
value = json.loads(data, object_pairs_hook=unique)
_canonical(value)
return value
except (UnicodeError, RecursionError) as exc:
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")View on GitHub (pinned to 8321021c54)