{"record":{"id":"08eee5b84c5759f8","repo":"affaan-m/ECC","slug":"at-least-one-video-is-required","errorCode":null,"errorMessage":"At least one video is required","messagePattern":"At least one video is required","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"skills/taste-application/scripts/tasteforge/media/capcut.py","lineNumber":63,"sourceCode":"    files,\n    drafts,\n    name,\n    width=1920,\n    height=1080,\n    fps=30,\n    overwrite=False,\n    cc=None,\n    probe=duration_of,\n):\n    geometry(width, height, fps)\n    if overwrite:\n        raise ValueError(\"CapCut draft replacement is unsafe; choose a new name\")\n    if not re.fullmatch(r\"[A-Za-z0-9][A-Za-z0-9_. -]{0,99}\", name) or name.endswith(\n        \".\"\n    ):\n        raise ValueError(\"Draft name must be a plain file name\")\n    if not files:\n        raise ValueError(\"At least one video is required\")\n    prepared = []\n    for filename in files:\n        path = Path(filename).resolve(strict=True)\n        duration = probe(path)\n        if not math.isfinite(duration) or duration <= 0:\n            raise ValueError(f\"Invalid media duration: {path.name}\")\n        prepared.append((str(path), duration))\n    if cc is None:\n        import pycapcut as cc\n    folder = cc.DraftFolder(str(drafts))\n    script = folder.create_draft(name, width, height, fps=fps, allow_replace=False)\n    script.add_track(cc.TrackType.video)\n    elapsed = 0\n    for filename, duration in prepared:\n        script.add_segment(\n            cc.VideoSegment(filename, cc.trange(f\"{elapsed:.6f}s\", f\"{duration:.6f}s\"))\n        )\n        elapsed += duration","sourceCodeStart":45,"sourceCodeEnd":81,"githubUrl":"https://github.com/affaan-m/ECC/blob/8321021c54d670126ce3b2969d5deb880b4b0c2a/skills/taste-application/scripts/tasteforge/media/capcut.py#L45-L81","documentation":"export_draft in capcut.py validates its inputs before building the CapCut draft: an empty files list means the timeline would have no video material, which the draft format cannot represent usefully.","triggerScenarios":"Calling export_draft(files=[], ...) or passing a files list that ended up empty, e.g. because read_concat returned no 'file' lines from an empty or all-comment concat file.","commonSituations":"Concat file with only comments/blank lines; a glob like glob('*.mp4') matching nothing in the wrong working directory; upstream filtering removing all files before the call.","solutions":["Pass at least one existing video path in the files list","Verify your concat file contains 'file <path>' lines if using read_concat","Check that the glob/directory you sourced the list from actually contains videos (print len(files) before calling)","Fix the working-directory or extension filter that emptied the list"],"exampleFix":"// before\nfiles = read_concat('concat.txt')  # only comments inside\nexport_draft(files, name='edit')\n\n// after\nfiles = read_concat('concat.txt')\nassert files, 'concat file produced no entries'\nexport_draft(files, name='edit')","handlingStrategy":"validation","validationCode":"files = read_concat('concat.txt')\nif not files:\n    raise SystemExit('no video entries found; concat file is empty or comment-only')","typeGuard":"def has_videos(files):\n    return bool(files) and all(Path(f).is_file() for f in files)","tryCatchPattern":"try:\n    export_draft(files, name=name)\nexcept ValueError as e:\n    if 'At least one video' in str(e):\n        sys.exit('concat manifest or glob produced no videos')","preventionTips":["Assert len(files) > 0 before every export call","Log the file list length at collection time (glob, concat, or CLI args)","Check concat files for comments-only content","Verify working directory when building lists with relative globs"],"tags":["python","capcut","empty-input","validation"],"backgroundTag":"empty-required-field","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"}