{"record":{"id":"7939872f296f6026","repo":"affaan-m/ECC","slug":"invalid-native-snapshot-track","errorCode":null,"errorMessage":"invalid native snapshot track","messagePattern":"invalid native snapshot track","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"skills/taste-application/scripts/tasteforge/integration.py","lineNumber":219,"sourceCode":"        if type(native_fps) not in (str, int, float):\n            raise ValueError(\"native fps missing\")\n        label = str(native_fps)\n        if not re.fullmatch(r\"[0-9]{1,9}(?:\\.[0-9]{1,12}|/[1-9][0-9]{0,8})?\", label):\n            raise ValueError(\"native fps must use a bounded decimal or rational label\")\n        native_rate = Fraction(ntsc.get(label, label))\n        if native_rate != Fraction(*_rate(baseline[\"fps\"])):\n            raise ValueError(\"native fps differs\")\n    except (ValueError, ZeroDivisionError) as exc:\n        raise ValueError(\"native snapshot fps is missing, invalid or contradictory\") from exc\n    for cfg, key in [(\"project_name\", \"project\"), (\"timeline_name\", \"timeline\")]:\n        if _text(baseline[cfg]) != snapshot.get(key):\n            raise ValueError(\"native snapshot identity mismatch\")\n    tracks = snapshot.get(\"timeline_readback\")\n    if not isinstance(tracks, dict) or not tracks:\n        raise ValueError(\"native clip snapshot required\")\n    for track, clips in tracks.items():\n        if not re.fullmatch(r\"(?:video|audio)[1-9][0-9]*\", track) or not isinstance(clips, list):\n            raise ValueError(\"invalid native snapshot track\")\n        for clip in clips:\n            _check_clip(clip, bounds)\n    return tracks\n\n\ndef _check_clip(clip: Any, bounds: list[int]) -> None:\n    required = {\"path\", \"name\", \"start\", \"end\", \"left_offset\", \"right_offset\", \"enabled\", \"properties\"}\n    if not isinstance(clip, dict) or not required <= clip.keys():\n        raise ValueError(\"native snapshot clip is incomplete\")\n    _range([clip[\"start\"], clip[\"end\"]], bounds)\n    _integer(clip[\"left_offset\"])\n    _integer(clip[\"right_offset\"])\n    if clip[\"path\"] is not None:\n        _text(clip[\"path\"])\n    _text(clip[\"name\"])\n    if type(clip[\"enabled\"]) is not bool or not isinstance(clip[\"properties\"], dict):\n        raise ValueError(\"native clip state is incomplete\")\n","sourceCodeStart":201,"sourceCodeEnd":237,"githubUrl":"https://github.com/affaan-m/ECC/blob/8321021c54d670126ce3b2969d5deb880b4b0c2a/skills/taste-application/scripts/tasteforge/integration.py#L201-L237","documentation":"Raised by _snapshot while validating the timeline_readback dict of a native snapshot. Every key must be a track name like 'video1' or 'audio2' (prefix 'video'/'audio' followed by a nonzero number) and every value must be a list of clips. This guard exists so downstream binding logic can rely on a well-formed track map.","triggerScenarios":"Calling build_application_bundle when snapshot['timeline_readback'] contains a key that fails the regex (e.g. 'video', 'v1', 'video0', 'video01' is fine as [1-9][0-9]* but 'video00' matches... note 'video0' fails since first digit must be 1-9), or a value that is not a list (dict, None, string).","commonSituations":"Manually hand-crafting a snapshot for tests, exporting a timeline under a nonstandard naming scheme from a native host app, or parsing a snapshot JSON where track lists were serialized as objects keyed by clip id.","solutions":["Rename snapshot track keys to the exact form 'video<n>' or 'audio<n>' with n starting at 1 (e.g. 'video1').","Ensure each track's value is a plain Python list of clip dicts, not a dict or None.","Log repr(snapshot['timeline_readback']) and compare each key against re.fullmatch(r\"(?:video|audio)[1-9][0-9]*\", key) before calling build_application_bundle."],"exampleFix":"// before\nsnapshot['timeline_readback'] = {'V1': [clip1], 'A1': [clip2]}\n// after\nsnapshot['timeline_readback'] = {'video1': [clip1], 'audio1': [clip2]}","handlingStrategy":"validation","validationCode":"import re\ntracks = snapshot.get('timeline_readback', {})\nfor track, clips in tracks.items():\n    assert re.fullmatch(r'(?:video|audio)[1-9][0-9]*', track), f'bad track key: {track}'\n    assert isinstance(clips, list), f'track {track} value is not a list'","typeGuard":"def is_valid_track_map(tracks) -> bool:\n    return (\n        isinstance(tracks, dict) and bool(tracks)\n        and all(\n            isinstance(k, str)\n            and re.fullmatch(r'(?:video|audio)[1-9][0-9]*', k) is not None\n            and isinstance(v, list)\n            for k, v in tracks.items()\n        )\n    )","tryCatchPattern":"try:\n    bundle = build_application_bundle(...)\nexcept ValueError as e:\n    if 'invalid native snapshot track' in str(e):\n        log.error('snapshot timeline_readback malformed', snapshot_tracks=list(snapshot.get('timeline_readback', {})))\n    raise","preventionTips":["Always generate snapshots via the library's own export path, never hand-built dicts","Normalize track keys to video<n>/audio<n> starting at 1","Validate snapshot JSON against the expected schema before calling build_application_bundle"],"tags":["validation","snapshot","media"],"backgroundTag":"invalid-argument-format","analyzedSha":"8321021c54d670126ce3b2969d5deb880b4b0c2a","analyzedAt":"2026-09-16T10:08:13.343Z","contentChangedAt":"2026-09-16T10:08:13.343Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}