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

  1. Point baseline.snapshot_file at the single-object snapshot export, not an array of snapshots.
  2. If you have an array, select the intended element and write it as the root object.
  3. Fix the exporter so it emits a single JSON object per snapshot file.
  4. 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

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


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)