{"record":{"id":"c526f5639634b43d","repo":"hiyouga/LlamaFactory","slug":"invalid-image-found-in-video-frames","errorCode":null,"errorMessage":"Invalid image found in video frames.","messagePattern":"Invalid image found in video frames\\.","errorType":"exception","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"src/llamafactory/data/mm_plugin.py","lineNumber":287,"sourceCode":"                    image = Image.open(image[\"path\"])\n\n            if not isinstance(image, ImageObject):\n                raise ValueError(f\"Expect input is a list of images, but got {type(image)}.\")\n\n            results.append(self._preprocess_image(image, **kwargs))\n\n        return {\"images\": results}\n\n    def _regularize_videos(self, videos: list[\"VideoInput\"], **kwargs) -> \"RegularizedVideoOutput\":\n        r\"\"\"Regularizes videos to avoid error. Including reading, resizing and converting.\"\"\"\n        results = []\n        durations = []\n        for video in videos:\n            frames: list[ImageObject] = []\n            if _check_video_is_nested_images(video):\n                for frame in video:\n                    if not is_valid_image(frame) and not isinstance(frame, dict) and not os.path.exists(frame):\n                        raise ValueError(\"Invalid image found in video frames.\")\n                frames = video\n                durations.append(len(frames) / kwargs.get(\"video_fps\", 2.0))\n            else:\n                container = av.open(video, \"r\")\n                video_stream = next(stream for stream in container.streams if stream.type == \"video\")\n                sample_indices = self._get_video_sample_indices(video_stream, **kwargs)\n                container.seek(0)\n                for frame_idx, frame in enumerate(container.decode(video_stream)):\n                    if frame_idx in sample_indices:\n                        frames.append(frame.to_image())\n\n                if video_stream.duration is None:\n                    durations.append(len(frames) / kwargs.get(\"video_fps\", 2.0))\n                else:\n                    durations.append(float(video_stream.duration * video_stream.time_base))\n\n            frames = self._regularize_images(frames, **kwargs)[\"images\"]\n            results.append(frames)","sourceCodeStart":269,"sourceCodeEnd":305,"githubUrl":"https://github.com/hiyouga/LlamaFactory/blob/f28afaf6355af515454dfb16c97d728307c93897/src/llamafactory/data/mm_plugin.py#L269-L305","documentation":"Thrown in BasePlugin._regularize_videos when a video supplied as a nested list of frames contains a frame that is not a valid image, not a dict descriptor, and not an existing filesystem path. LlamaFactory accepts pre-sampled frame lists, but each frame must be loadable (PIL Image, bytes dict, or path).","triggerScenarios":"A dataset 'videos' column containing [[frame1, frame2], ...] where a frame is None, a numpy array, or a path string to a file that does not exist (os.path.exists fails, e.g. relative path resolved from the wrong cwd).","commonSituations":"Pre-sampled frame datasets converted from video files where the frame paths are relative and training runs from a different working directory; frames serialized as arrays; missing frame files after moving the dataset.","solutions":["Verify every frame path exists from the process's actual cwd; use absolute paths or set dataset_dir correctly.","Convert numpy/array frames to PIL Images or {'bytes': ...} dicts.","Drop or repair rows with None frames."],"exampleFix":"# before\n\"videos\": [[\"frames/f0001.jpg\", \"frames/f0002.jpg\"]]  # relative, cwd-dependent\n# after\n\"videos\": [[\"/data/vid1/f0001.jpg\", \"/data/vid1/f0002.jpg\"]]","handlingStrategy":"validation","validationCode":"import os\nfrom PIL import Image\n\ndef frames_ok(frames):\n    for f in frames:\n        if isinstance(f, Image.Image) or isinstance(f, dict):\n            continue\n        if isinstance(f, str) and os.path.isfile(f):\n            continue\n        return False\n    return True","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Use absolute paths for frame files in datasets.","Validate frame lists in the data-prep script, not at train time."],"tags":["multimodal","video","frames","path-resolution"],"backgroundTag":null,"analyzedSha":"f28afaf6355af515454dfb16c97d728307c93897","analyzedAt":"2026-08-14T21:57:28.298Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}