hiyouga/LlamaFactory · error · ValueError
Unsupported dummy media modality: {modality!r} (expected ima
Error message
Unsupported dummy media modality: {modality!r} (expected image/video/audio). What it means
Renderer.get_dummy_media_fragment(modality) only accepts 'image', 'video', or 'audio'. Any other string (typos like 'img', 'Audio', or future modalities) is rejected immediately with the allowed set echoed in the message.
Source
Thrown at src/llamafactory/v1/core/rendering/rendering.py:211
Args:
messages: The messages to render. For training the last message must be the supervised
assistant turn (use ``process_samples`` to split multi-turn conversations).
tools: JSON string of tool definitions.
is_generate: Whether to render for generation (adds generation prompt, no supervision).
**kwargs: Extra chat-template kwargs (e.g. ``enable_thinking``) forwarded verbatim to
``apply_chat_template``; unset ones fall back to the template's own defaults. A
supervised assistant turn carrying reasoning forces ``enable_thinking=True``.
Returns:
ModelInput with input_ids, attention_mask, labels, and loss_weights.
"""
return _render_messages(self.processor, messages, tools, is_generate, **kwargs)
def get_dummy_media_fragment(self, modality: str) -> dict:
"""Build (and cache) a minimal valid media fragment for ``modality`` ("image"|"video"|"audio")."""
if modality not in ("image", "video", "audio"):
raise ValueError(f"Unsupported dummy media modality: {modality!r} (expected image/video/audio).")
if is_tokenizer(self.processor):
raise RuntimeError("Cannot build a dummy media fragment for a text-only processor.")
if not hasattr(self, "_dummy_fragments"):
self._dummy_fragments: dict[str, dict] = {}
if modality in self._dummy_fragments:
return self._dummy_fragments[modality]
from PIL import Image as _PILImage
if modality == "image":
media_block = {"type": "image_url", "value": _PILImage.new("RGB", (64, 64))}
target, presence_key = 1, "pixel_values"
elif modality == "video":
# A minimal clip: the temporal patch size is typically 2, so provide two frames.
media_block = {"type": "video_url", "value": np.zeros((2, 64, 64, 3), dtype=np.uint8)}
target, presence_key = 2, "pixel_values_videos"
else:View on GitHub (pinned to f28afaf635)
Solutions
- Pass one of exactly 'image', 'video', 'audio' (lowercase)
- Map content block types before calling: 'image_url'->'image', 'video_url'->'video', 'audio_url'->'audio'
- Validate the modality against the allowed set at the call site for a clearer upstream error
Example fix
# before
frag = renderer.get_dummy_media_fragment(block["type"]) # 'image_url' -> ValueError
# after
_MOD = {"image_url": "image", "video_url": "video", "audio_url": "audio"}
frag = renderer.get_dummy_media_fragment(_MOD[block["type"]]) Defensive patterns
Strategy: type-guard
Type guard
def is_supported_modality(m: str) -> bool:
return m in ("image", "video", "audio") Prevention
- Map content block types to canonical modality names before calling
- Freeze the allowed set in a shared constant used by all call sites
When it happens
Trigger: Calling get_dummy_media_fragment with a modality string outside {'image','video','audio'} — commonly a typo, a caller-derived modality name, or case mismatch ('Image').
Common situations: Generic multimodal plumbing that derives the modality from content block types like 'image_url' and passes it unnormalized.
Related errors
- tool_call value is not valid JSON: {content['value']!r}
- tool_call must be a JSON object with 'name' and 'arguments'
- {kind} placeholder count ({seen}) != number of {kind} blocks
- Cannot build a dummy media fragment for a text-only processo
- Processor did not emit {modality} placeholder tokens for the
AI-assisted analysis of hiyouga/LlamaFactory@f28afaf635 (2026-08-14).
Data as JSON: /api/errors/16bd2d4a320a9f8b.
Report an issue: GitHub.