hiyouga/LlamaFactory · error · ValueError
Invalid image found in video frames.
Error message
Invalid image found in video frames.
What it means
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).
Source
Thrown at src/llamafactory/data/mm_plugin.py:287
image = Image.open(image["path"])
if not isinstance(image, ImageObject):
raise ValueError(f"Expect input is a list of images, but got {type(image)}.")
results.append(self._preprocess_image(image, **kwargs))
return {"images": results}
def _regularize_videos(self, videos: list["VideoInput"], **kwargs) -> "RegularizedVideoOutput":
r"""Regularizes videos to avoid error. Including reading, resizing and converting."""
results = []
durations = []
for video in videos:
frames: list[ImageObject] = []
if _check_video_is_nested_images(video):
for frame in video:
if not is_valid_image(frame) and not isinstance(frame, dict) and not os.path.exists(frame):
raise ValueError("Invalid image found in video frames.")
frames = video
durations.append(len(frames) / kwargs.get("video_fps", 2.0))
else:
container = av.open(video, "r")
video_stream = next(stream for stream in container.streams if stream.type == "video")
sample_indices = self._get_video_sample_indices(video_stream, **kwargs)
container.seek(0)
for frame_idx, frame in enumerate(container.decode(video_stream)):
if frame_idx in sample_indices:
frames.append(frame.to_image())
if video_stream.duration is None:
durations.append(len(frames) / kwargs.get("video_fps", 2.0))
else:
durations.append(float(video_stream.duration * video_stream.time_base))
frames = self._regularize_images(frames, **kwargs)["images"]
results.append(frames)View on GitHub (pinned to f28afaf635)
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.
Example fix
# before "videos": [["frames/f0001.jpg", "frames/f0002.jpg"]] # relative, cwd-dependent # after "videos": [["/data/vid1/f0001.jpg", "/data/vid1/f0002.jpg"]]
Defensive patterns
Strategy: validation
Validate before calling
import os
from PIL import Image
def frames_ok(frames):
for f in frames:
if isinstance(f, Image.Image) or isinstance(f, dict):
continue
if isinstance(f, str) and os.path.isfile(f):
continue
return False
return True Prevention
- Use absolute paths for frame files in datasets.
- Validate frame lists in the data-prep script, not at train time.
When it happens
Trigger: 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).
Common situations: 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.
Related errors
- MOSS-VL video frame tokens do not match the processed video
- This model does not support video input. Please check whethe
- The number of videos does not match the number of {VIDEO_PLA
- MOSS-VL encountered nested video token blocks after tokeniza
- MOSS-VL encountered a video end token without a matching sta
AI-assisted analysis of hiyouga/LlamaFactory@f28afaf635 (2026-08-14).
Data as JSON: /api/errors/c526f5639634b43d.
Report an issue: GitHub.