{"record":{"id":"532fa2059ad1dba4","repo":"affaan-m/ECC","slug":"source-binding-has-no-native-clip","errorCode":null,"errorMessage":"source binding has no native clip","messagePattern":"source binding has no native clip","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"skills/taste-application/scripts/tasteforge/integration.py","lineNumber":246,"sourceCode":"        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\n\ndef _binding(item: Any, tracks: dict, baseline: dict, *, audio: bool = False) -> tuple:\n    _object(item, {\"media\", \"track\", \"clip_index\", \"media_frames\", \"fps\",\n                   \"source_range\", \"timeline_range\"})\n    track, index = _text(item[\"track\"]), _integer(item[\"clip_index\"])\n    if not track.startswith(\"audio\" if audio else \"video\"):\n        raise ValueError(\"wrong source/audio track kind\")\n    if track not in tracks or index >= len(tracks[track]):\n        raise ValueError(\"source binding has no native clip\")\n    clip = tracks[track][index]\n    _artifact(item[\"media\"])\n    if item[\"media\"][\"path\"] != clip[\"path\"]:\n        raise ValueError(\"source path does not match native clip\")\n    if _rate(item[\"fps\"]) != _rate(baseline[\"fps\"]):\n        raise ValueError(\"source fps/retime ambiguity\")\n    duration = clip[\"end\"] - clip[\"start\"]\n    capacity = _integer(item[\"media_frames\"], 1)\n    if capacity != clip[\"left_offset\"] + duration + clip[\"right_offset\"]:\n        raise ValueError(\"source capacity does not match native offsets\")\n    source = _range(item[\"source_range\"], [clip[\"left_offset\"], clip[\"left_offset\"] + duration])\n    target = _range(item[\"timeline_range\"], [clip[\"start\"], clip[\"end\"]])\n    mapped = [clip[\"start\"] + f - clip[\"left_offset\"] for f in source]\n    if mapped != target or (audio and target != [clip[\"start\"], clip[\"end\"]]):\n        raise ValueError(\"source/audio placement must preserve native timing\")\n    return track, index\n\n","sourceCodeStart":228,"sourceCodeEnd":264,"githubUrl":"https://github.com/affaan-m/ECC/blob/8321021c54d670126ce3b2969d5deb880b4b0c2a/skills/taste-application/scripts/tasteforge/integration.py#L228-L264","documentation":"Raised by _binding when the referenced track is absent from the validated snapshot's timeline_readback, or the clip_index equals or exceeds the number of clips on that track. The binding must point at a real, existing native clip.","triggerScenarios":"A binding item with track='video3' when the snapshot only defines video1/video2, or track='video1' with clip_index=2 when video1 has only 2 clips (indices 0 and 1).","commonSituations":"Timeline was shortened or re-exported and clip indices shifted; bindings cached from an older snapshot; off-by-one when building clip_index from 1-based UI data.","solutions":["Ensure the binding's track exists in snapshot['timeline_readback'] and that clip_index < len(tracks[track]).","Regenerate bindings from the current snapshot instead of reusing stale ones after timeline edits.","Subtract 1 if your source data uses 1-based clip numbering before setting clip_index."],"exampleFix":"// before\n{'track': 'video1', 'clip_index': 2}  # video1 has 2 clips (0,1)\n// after\n{'track': 'video1', 'clip_index': 1}","handlingStrategy":"validation","validationCode":"tracks = snapshot['timeline_readback']\nfor item in bindings:\n    assert item['track'] in tracks, f\"unknown track {item['track']}\"\n    assert 0 <= item['clip_index'] < len(tracks[item['track']]), f\"clip_index out of range on {item['track']}\"","typeGuard":"def binding_targets_existing_clip(item, tracks) -> bool:\n    return item['track'] in tracks and 0 <= item['clip_index'] < len(tracks[item['track']])","tryCatchPattern":"try:\n    bundle = build_application_bundle(...)\nexcept ValueError as e:\n    if 'source binding has no native clip' in str(e):\n        log.error('stale binding', bindings=bindings, tracks={k: len(v) for k, v in snapshot['timeline_readback'].items()})\n    raise","preventionTips":["Regenerate bindings whenever the snapshot is re-exported","Use 0-based indices consistently; convert from 1-based UI data","Assert binding targets against the snapshot in tests"],"tags":["binding","index-out-of-range","snapshot"],"backgroundTag":"index-out-of-bounds","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"}