{"record":{"id":"2b9b67b9022ed94b","repo":"affaan-m/ECC","slug":"source-timeline-must-be-explicit","errorCode":null,"errorMessage":"source_timeline must be explicit","messagePattern":"source_timeline must be explicit","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"skills/taste-application/scripts/tasteforge/resolve.py","lineNumber":253,"sourceCode":"    placements,\n    *,\n    source_timeline,\n    source_end_mode,\n    fps,\n    base_track_count,\n    probe=probe_asset,\n):\n    \"\"\"Append and verify overlays; returns an in-memory placement receipt only.\n\n    This does not save/export/render a project. Supply the selected target's\n    media pool. Existing overlay tracks must be empty; base tracks are preserved.\n    source_end_mode is required: use the endpoint convention verified on this\n    Resolve host. No automatic retry occurs if that convention is incorrect.\n    \"\"\"\n    if source_end_mode not in (\"inclusive\", \"exclusive\"):\n        raise ValueError(\"source_end_mode must be inclusive or exclusive\")\n    if not isinstance(source_timeline, str) or not source_timeline:\n        raise ValueError(\"source_timeline must be explicit\")\n    name = timeline.GetName()\n    if not name or name == source_timeline:\n        raise ValueError(\"target must be a distinct versioned timeline\")\n    plan = allocate_placements(\n        placements, fps=fps, base_track_count=base_track_count, probe=probe\n    )\n    if _fps(timeline.GetSetting(\"timelineFrameRate\")) != _fps(fps):\n        raise ValueError(\"target timeline fps mismatch\")\n    count = timeline.GetTrackCount(\"video\")\n    if count < base_track_count:\n        raise ValueError(\"base_track_count exceeds target video tracks\")\n    for track in range(base_track_count + 1, count + 1):\n        if _items(timeline, \"video\", track):\n            raise ValueError(\"target overlay tracks must be empty\")\n    before = _base_snapshot(timeline, base_track_count)\n    for _ in range(count, max(event[\"track\"] for event in plan)):\n        old_count = timeline.GetTrackCount(\"video\")\n        if (","sourceCodeStart":235,"sourceCodeEnd":271,"githubUrl":"https://github.com/affaan-m/ECC/blob/8321021c54d670126ce3b2969d5deb880b4b0c2a/skills/taste-application/scripts/tasteforge/resolve.py#L235-L271","documentation":"The source timeline name must be a non-empty explicit string. apply_placements compares the target timeline's name against it to enforce the target is a distinct versioned copy, so a missing/blank source name cannot be tolerated. Validated before any mutation.","triggerScenarios":"Calling apply_placements/apply with source_timeline=None, \"\", a non-string (e.g. a timeline object), or whitespace-only value.","commonSituations":"CLI flag not passed through to the function; config key read from an unset env var; refactoring where the timeline object was passed instead of its name.","solutions":["Pass the exact source timeline name string, e.g. source_timeline=\"master_v3\"","Fix the caller to extract timeline.GetName() if you have an object","Check config/env plumbing so the name isn't dropped before the call"],"exampleFix":"// before\napply_placements(timeline, pool, placements, source_timeline=source_tl_obj)\n// after\napply_placements(timeline, pool, placements, source_timeline=source_tl_obj.GetName())","handlingStrategy":"validation","validationCode":"if not isinstance(source_timeline, str) or not source_timeline.strip():\n    raise ValueError(\"source_timeline must be a non-empty string name\")","typeGuard":"def is_nonempty_str(v) -> bool:\n    return isinstance(v, str) and bool(v.strip())","tryCatchPattern":"try:\n    apply_placements(..., source_timeline=name)\nexcept ValueError as exc:\n    if \"source_timeline\" in str(exc):\n        print(\"Pass the source timeline NAME, not an object or empty value\")\n    raise","preventionTips":["Pass timeline.GetName() when you hold a timeline object","Validate config values are non-empty strings before calling","Type the parameter as str (not Optional) in your wrappers","Fail fast in CLI arg parsing when the source name is missing"],"tags":["validation","arguments","resolve-api"],"backgroundTag":"missing-required-argument","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"}