hiyouga/LlamaFactory · error · ValueError

Expect input is a list of images, but got {type(image)}.

Error message

Expect input is a list of images, but got {type(image)}.

What it means

Thrown in BasePlugin._regularize_images when an element of the `images` list cannot be coerced into a PIL Image. Supported inputs are: file path str / file-like object (opened via Image.open), raw bytes, a dict with 'bytes' or 'path' keys, or an already-loaded PIL Image. Anything else (int, None, numpy array, broken object) reaches the isinstance check and fails.

Source

Thrown at src/llamafactory/data/mm_plugin.py:272

        r"""Build metadata used to expand video tokens without decoding frames."""
        return None

    def _regularize_images(self, images: list["ImageInput"], **kwargs) -> "RegularizedImageOutput":
        r"""Regularize images to avoid error. Including reading and pre-processing."""
        results = []
        for image in images:
            if isinstance(image, (str, BinaryIO)):
                image = Image.open(image)
            elif isinstance(image, bytes):
                image = Image.open(BytesIO(image))
            elif isinstance(image, dict):
                if image["bytes"] is not None:
                    image = Image.open(BytesIO(image["bytes"]))
                else:
                    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:

View on GitHub (pinned to f28afaf635)

Solutions

  1. Convert each image to PIL before passing: Image.fromarray(arr) for numpy, or pass file paths / {'bytes': ..., 'path': ...} dicts.
  2. Filter or repair rows with null/missing image values in the dataset.
  3. Ensure you pass a list of images, not a bare image or nested lists.

Example fix

# before
images = [np_array]  # numpy RGB array
# after
from PIL import Image
images = [Image.fromarray(np_array)]
Defensive patterns

Strategy: type-guard

Validate before calling

from PIL import Image

def valid_image_inputs(images):
    for im in images:
        if isinstance(im, (str, bytes, dict)) or isinstance(im, Image.Image):
            continue
        if hasattr(im, 'read'):  # file-like
            continue
        return False
    return True

Type guard

from PIL import Image
from typing import Union

ImageInputOK = Union[str, bytes, dict, Image.Image]

def is_image_input(x) -> bool:
    return isinstance(x, (str, bytes, dict, Image.Image)) or hasattr(x, 'read')

Try / catch

try:
    mm = plugin.process_messages(messages, images, [], [], processor)
except ValueError as e:
    if 'list of images' in str(e):
        images = [Image.open(p) if isinstance(p, str) else p for p in images]
    else:
        raise

Prevention

When it happens

Trigger: Passing images as numpy arrays, torch tensors, None entries, or a single Image instead of a list to _regularize_images / process_messages. Also a dict without 'bytes'/'path' keys, or an object whose type is not PIL.Image.Image.

Common situations: Datasets stored as decoded numpy frames; a column that is null for some rows; iterating a column that yields scalars; HF datasets pushing an unexpected Arrow type.

Related errors


AI-assisted analysis of hiyouga/LlamaFactory@f28afaf635 (2026-08-14). Data as JSON: /api/errors/2fc2a842812b7e58. Report an issue: GitHub.