{"record":{"id":"1a80dd14a214760c","repo":"affaan-m/ECC","slug":"no-repeat-media-must-contain-unique-normalized-source-paths","errorCode":null,"errorMessage":"no-repeat media must contain unique normalized source paths","messagePattern":"no-repeat media must contain unique normalized source paths","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"skills/taste-application/scripts/tasteforge/apply.py","lineNumber":88,"sourceCode":"        if boundary <= assigned:\n            raise ValueError(\"cadence shot cannot occupy a whole frame\")\n        frame_counts.append(boundary - assigned)\n        assigned = boundary\n    if assigned < target_frames:\n        frame_counts.append(target_frames - assigned)\n\n    rate = timeline.fps_fraction(fps)\n    sources: dict[str, tuple[dict[str, Any], int]] = {}\n    for clip in media:\n        path = str(Path(clip[\"path\"]).expanduser().resolve())\n        # Floor rational capacity: rounding up could read past the source end.\n        capacity = math.floor(Fraction(str(clip[\"duration\"])) * rate)\n        # Accept a boundary serialized as a float only when the frame duration\n        # itself compares within the supplied duration; no broad epsilon.\n        if float((capacity + 1) / rate) <= clip[\"duration\"]:\n            capacity += 1\n        if path in sources:\n            raise ValueError(\"no-repeat media must contain unique normalized source paths\")\n        sources[path] = ({**clip, \"path\": path}, capacity)\n    if len(sources) < len(frame_counts):\n        raise ValueError(\"no-repeat plan requires more unique source clips\")\n    assignments = []\n    for (clip, capacity), count in zip(sources.values(), frame_counts):\n        if capacity < count:\n            raise ValueError(\"source clip is too short for its no-repeat cadence slot\")\n        assignments.append((clip, count))\n    return assignments\n\n\n\ndef plan_shots(cadence: dict[str, Any], target_duration: float) -> list[float]:\n    \"\"\"Propose shot durations filling ``target_duration`` at this cadence.\n\n    Samples from the reference's own shot-length distribution (seeded, like\n    the recovered ``Cadence.plan_shots``) so the plan inherits rhythm\n    variance instead of flattening into evenly spaced clips.","sourceCodeStart":70,"sourceCodeEnd":106,"githubUrl":"https://github.com/affaan-m/ECC/blob/8321021c54d670126ce3b2969d5deb880b4b0c2a/skills/taste-application/scripts/tasteforge/apply.py#L70-L106","documentation":"In the no-repeat mode, each media clip is keyed by its normalized source path in the `sources` dict. If two clips resolve to the same normalized path, the no-repeat invariant (each source used once per slot) would be broken, so a duplicate key raises this error.","triggerScenarios":"Passing `media` to `apply_local` with duplicate clips pointing at the same normalized source path, e.g. the same file listed twice or via aliases that normalize identically.","commonSituations":"A media directory scanned twice; the same clip referenced with different relative/absolute paths or `./` prefixes that normalization collapses; duplicate entries in a manifest built by concatenating playlists.","solutions":["Deduplicate media by normalized path before calling apply_local (use a dict/set keyed on the normalized path)","Fix the manifest generator to skip clips whose path was already added","If repetition is intended, do not use the no-repeat mode / disable the no-repeat constraint","Normalize paths consistently (resolve symlinks, absolute paths) so duplicates are detected upstream"],"exampleFix":"# before\nmedia = [{\"path\": \"a.mp4\"}, {\"path\": \"./a.mp4\"}]\n# after\nseen = {}\nfor c in media:\n    p = os.path.normpath(os.path.abspath(c[\"path\"]))\n    seen.setdefault(p, {**c, \"path\": p})\nmedia = list(seen.values())","handlingStrategy":"validation","validationCode":"paths = [os.path.normpath(os.path.abspath(c[\"path\"])) for c in media]\nif len(paths) != len(set(paths)):\n    raise ValueError(\"duplicate media source paths\")","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Deduplicate media by normalized absolute path before applying","Resolve symlinks (os.path.realpath) so aliases collapse to one entry","Deduplicate at manifest-generation time, not application time"],"tags":["media","duplicate","no-repeat"],"backgroundTag":"invalid-argument-value","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"}