{"record":{"id":"55229facaf586b84","repo":"hiyouga/LlamaFactory","slug":"cannot-build-a-dummy-media-fragment-for-a-text-onl","errorCode":null,"errorMessage":"Cannot build a dummy media fragment for a text-only processor.","messagePattern":"Cannot build a dummy media fragment for a text-only processor\\.","errorType":"exception","errorClass":"RuntimeError","httpStatus":null,"severity":"error","filePath":"src/llamafactory/v1/core/rendering/rendering.py","lineNumber":213,"sourceCode":"            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:\n            # A short synthetic waveform at the model's sampling rate; the feature extractor pads it.\n            sr = self.processor.feature_extractor.sampling_rate","sourceCodeStart":195,"sourceCodeEnd":231,"githubUrl":"https://github.com/hiyouga/LlamaFactory/blob/f28afaf6355af515454dfb16c97d728307c93897/src/llamafactory/v1/core/rendering/rendering.py#L195-L231","documentation":"get_dummy_media_fragment is only meaningful for a multimodal processor (one with a feature extractor / image processor). If the renderer was constructed with a bare tokenizer (is_tokenizer(processor) is True), there is no way to produce valid pixel/audio tensors, so a RuntimeError is raised.","triggerScenarios":"Building the renderer with tokenizer-only (text model) and then calling get_dummy_media_fragment for any modality — typically in generic padding/batching code that unconditionally requests dummy fragments.","commonSituations":"Shared collation code reused across text-only and multimodal models; forgetting to gate the dummy-fragment path on model modality.","solutions":["Gate the call on modality: only request dummy fragments when the model is multimodal (processor is not a plain tokenizer)","Use the renderer's is_tokenizer-safe check or hasattr(processor, 'feature_extractor')/'image_processor' before calling","For text-only models, pad with pure text fragments instead"],"exampleFix":"# before\nfrag = renderer.get_dummy_media_fragment(\"image\")  # renderer built from a tokenizer\n\n# after\nfrom llamafactory.v1.core.rendering.rendering import is_tokenizer\nfrag = None if is_tokenizer(renderer.processor) else renderer.get_dummy_media_fragment(\"image\")","handlingStrategy":"type-guard","validationCode":null,"typeGuard":"def renderer_supports_media(renderer) -> bool:\n    return not is_tokenizer(renderer.processor)  # multimodal processor present","tryCatchPattern":null,"preventionTips":["Branch collation code on processor type (tokenizer vs multimodal processor)","Expose a supports_media flag from your model wrapper and check it before dummy-fragment requests"],"tags":["multimodal","text-only","api-misuse","processor"],"backgroundTag":null,"analyzedSha":"f28afaf6355af515454dfb16c97d728307c93897","analyzedAt":"2026-08-14T21:57:28.298Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}