{"record":{"id":"16bd2d4a320a9f8b","repo":"hiyouga/LlamaFactory","slug":"unsupported-dummy-media-modality-modality-r-ex","errorCode":null,"errorMessage":"Unsupported dummy media modality: {modality!r} (expected image/video/audio).","messagePattern":"Unsupported dummy media modality: (.+?) \\(expected image/video/audio\\)\\.","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"src/llamafactory/v1/core/rendering/rendering.py","lineNumber":211,"sourceCode":"\n        Args:\n            messages: The messages to render. For training the last message must be the supervised\n                assistant turn (use ``process_samples`` to split multi-turn conversations).\n            tools: JSON string of tool definitions.\n            is_generate: Whether to render for generation (adds generation prompt, no supervision).\n            **kwargs: Extra chat-template kwargs (e.g. ``enable_thinking``) forwarded verbatim to\n                ``apply_chat_template``; unset ones fall back to the template's own defaults. A\n                supervised assistant turn carrying reasoning forces ``enable_thinking=True``.\n\n        Returns:\n            ModelInput with input_ids, attention_mask, labels, and loss_weights.\n        \"\"\"\n        return _render_messages(self.processor, messages, tools, is_generate, **kwargs)\n\n    def get_dummy_media_fragment(self, modality: str) -> dict:\n        \"\"\"Build (and cache) a minimal valid media fragment for ``modality`` (\"image\"|\"video\"|\"audio\").\"\"\"\n        if modality not in (\"image\", \"video\", \"audio\"):\n            raise ValueError(f\"Unsupported dummy media modality: {modality!r} (expected image/video/audio).\")\n        if is_tokenizer(self.processor):\n            raise RuntimeError(\"Cannot build a dummy media fragment for a text-only processor.\")\n\n        if not hasattr(self, \"_dummy_fragments\"):\n            self._dummy_fragments: dict[str, dict] = {}\n        if modality in self._dummy_fragments:\n            return self._dummy_fragments[modality]\n\n        from PIL import Image as _PILImage\n\n        if modality == \"image\":\n            media_block = {\"type\": \"image_url\", \"value\": _PILImage.new(\"RGB\", (64, 64))}\n            target, presence_key = 1, \"pixel_values\"\n        elif modality == \"video\":\n            # A minimal clip: the temporal patch size is typically 2, so provide two frames.\n            media_block = {\"type\": \"video_url\", \"value\": np.zeros((2, 64, 64, 3), dtype=np.uint8)}\n            target, presence_key = 2, \"pixel_values_videos\"\n        else:","sourceCodeStart":193,"sourceCodeEnd":229,"githubUrl":"https://github.com/hiyouga/LlamaFactory/blob/f28afaf6355af515454dfb16c97d728307c93897/src/llamafactory/v1/core/rendering/rendering.py#L193-L229","documentation":"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.","triggerScenarios":"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').","commonSituations":"Generic multimodal plumbing that derives the modality from content block types like 'image_url' and passes it unnormalized.","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"],"exampleFix":"# before\nfrag = renderer.get_dummy_media_fragment(block[\"type\"])  # 'image_url' -> ValueError\n\n# after\n_MOD = {\"image_url\": \"image\", \"video_url\": \"video\", \"audio_url\": \"audio\"}\nfrag = renderer.get_dummy_media_fragment(_MOD[block[\"type\"]])","handlingStrategy":"type-guard","validationCode":null,"typeGuard":"def is_supported_modality(m: str) -> bool:\n    return m in (\"image\", \"video\", \"audio\")","tryCatchPattern":null,"preventionTips":["Map content block types to canonical modality names before calling","Freeze the allowed set in a shared constant used by all call sites"],"tags":["multimodal","api-misuse","dummy-data","rendering"],"backgroundTag":null,"analyzedSha":"f28afaf6355af515454dfb16c97d728307c93897","analyzedAt":"2026-08-14T21:57:28.298Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}