{"record":{"id":"d20571811c4c0abc","repo":"ATH-MaaS/Pixelle-Video","slug":"videos-list-cannot-be-empty","errorCode":null,"errorMessage":"Videos list cannot be empty","messagePattern":"Videos list cannot be empty","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"pixelle_video/services/video.py","lineNumber":132,"sourceCode":"        bgm_volume: float = 0.2,\n        bgm_mode: Literal[\"once\", \"loop\"] = \"loop\"\n    ) -> str:\n        \"\"\"\n        Concatenate multiple videos into one\n\n        Args:\n            videos: List of video file paths to concatenate\n            output: Output video file path\n            method: Concatenation method\n                - \"demuxer\": Fast, no re-encoding (requires identical formats)\n                - \"filter\": Slower but handles different formats\n            bgm_path: Background music file path (optional)\n                - None: No BGM\n        \"\"\"\n        self._ensure_ffmpeg()\n\n        if not videos:\n            raise ValueError(\"Videos list cannot be empty\")\n        \n        if len(videos) == 1:\n            logger.info(f\"Only one video provided, copying to {output}\")\n            shutil.copy(videos[0], output)\n            return output\n        \n        logger.info(f\"Concatenating {len(videos)} videos using {method} method\")\n        \n        # Step 1: Concatenate videos\n        if bgm_path:\n            # If BGM needed, concatenate to temp file first\n            temp_output = output.replace('.mp4', '_no_bgm.mp4')\n            concat_result = self._concat_demuxer(videos, temp_output) if method == \"demuxer\" else self._concat_filter(videos, temp_output)\n            \n            # Step 2: Add BGM\n            logger.info(f\"Adding BGM: {bgm_path} (volume={bgm_volume}, mode={bgm_mode})\")\n            final_result = self._add_bgm_to_video(\n                video=concat_result,","sourceCodeStart":114,"sourceCodeEnd":150,"githubUrl":"https://github.com/ATH-MaaS/Pixelle-Video/blob/848b054e4fae40dabc62ec58e960b573e83793ac/pixelle_video/services/video.py#L114-L150","documentation":"concat_videos validates its input before doing any work: an empty list of video paths cannot produce a concatenation, so it raises ValueError immediately (after _ensure_ffmpeg). This is a caller-contract error, not an FFmpeg failure.","triggerScenarios":"Calling concat_videos([]) or passing a list that ended up empty because an upstream filtering step removed all candidate files (e.g. glob matched nothing, all files failed validation).","commonSituations":"Dynamic pipelines where segments are generated conditionally and all generation steps failed; glob patterns with wrong extensions returning no matches; refactored code that now returns a list instead of a tuple and drops a default item.","solutions":["Check that the videos list is non-empty before calling concat_videos and handle the empty case explicitly (skip the step, or raise a domain-specific error).","Fix the upstream generation/glob logic so at least one input video exists.","If a single video is intended, pass it anyway — the method handles len==1 by copying it to output."],"exampleFix":"// before\nservice.concat_videos(segments, 'final.mp4')  # ValueError if segments == []\n// after\nif not segments:\n    raise ValueError(f'No video segments produced in {segments_dir}')\nservice.concat_videos(segments, 'final.mp4')","handlingStrategy":"validation","validationCode":"if not videos:\n    raise ValueError('No videos to concatenate')\nfor v in videos:\n    if not os.path.isfile(v):\n        raise FileNotFoundError(v)","typeGuard":"def is_nonempty_file_list(videos: object) -> bool:\n    return isinstance(videos, list) and len(videos) > 0 and all(isinstance(v, str) and os.path.isfile(v) for v in videos)","tryCatchPattern":"try:\n    service.concat_videos(videos, out)\nexcept ValueError as e:\n    if 'empty' in str(e):\n        logger.warning('No segments produced; skipping concat')\n        return None\n    raise","preventionTips":["Guard the list for emptiness at the pipeline boundary before calling concat_videos.","Check upstream generation steps: if all segment creation failed, stop early with a clear message.","Log the number of segments before concatenation to catch silently-empty lists.","Prefer passing a single video rather than special-casing around the empty case."],"tags":["validation","argument-error"],"backgroundTag":"empty-input-list","analyzedSha":"848b054e4fae40dabc62ec58e960b573e83793ac","analyzedAt":"2026-08-30T03:24:41.468Z","schemaVersion":2},"datasetVersion":"2026-08-30T08:17:16.595Z"}