{"record":{"id":"1b14cd49cd26d752","repo":"sgl-project/sglang","slug":"kimi-image-placeholders-must-map-one-to-one-to-ima-1b14cd","errorCode":null,"errorMessage":"Kimi image placeholders must map one-to-one to image data: expected {expected_image_count}, loaded {len(base_output.images)}","messagePattern":"Kimi image placeholders must map one-to-one to image data: expected (.+?), loaded (.+?)","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"python/sglang/srt/multimodal/processors/kimi_vl.py","lineNumber":44,"sourceCode":"            image_token_regex=re.compile(r\"(?:<\\|media_pad\\|>)+\"),\n        ).build(_processor)\n\n    async def process_mm_data_async(\n        self,\n        image_data: List[Union[str, bytes, Dict]],\n        input_text,\n        request_obj,\n        *args,\n        **kwargs,\n    ):\n        base_output = await self.load_mm_data(\n            prompt=input_text,\n            image_data=image_data,\n            multimodal_tokens=self.mm_tokens,\n        )\n        expected_image_count = len(image_data or [])\n        if len(base_output.images) != expected_image_count:\n            raise ValueError(\n                \"Kimi image placeholders must map one-to-one to image data: \"\n                f\"expected {expected_image_count}, loaded {len(base_output.images)}\"\n            )\n\n        mm_items, input_ids, _ = await self.process_and_combine_mm_data_async(\n            base_output, self.mm_tokens\n        )\n\n        return MultimodalProcessorOutput(\n            input_ids=input_ids.tolist(),\n            mm_items=mm_items,\n            im_token_id=self.mm_tokens.image_token_id,\n        )\n\n    def get_mm_data(self, prompt, embeddings, **kwargs):\n        img_grid_thw = kwargs.get(\"img_grid_thw\", None)\n        return self._build_kimi_mm_data_from_grids(\n            prompt=prompt,","sourceCodeStart":26,"sourceCodeEnd":62,"githubUrl":"https://github.com/sgl-project/sglang/blob/0132848349585cfe6aae51c4941cbae872505f8a/python/sglang/srt/multimodal/processors/kimi_vl.py#L26-L62","documentation":"Kimi VL multimodal processor requires that the number of image placeholders in the prompt exactly equals the number of supplied image_data entries. After loading, the base processor returned a different count of images than expected, so a one-to-one mapping cannot be established.","triggerScenarios":"Calling process_mm_data_async on the Kimi VL processor where the prompt contains N image placeholder tokens but image_data has M != N entries (e.g. placeholder repeated, or image list truncated/duplicated before reaching the processor).","commonSituations":"Client sends an OpenAI-style request whose content array has more/fewer image_url parts than the (image_start_id...image_end_id) placeholder occurrences in the text template; or a middleware rewrites the prompt and breaks placeholder count.","solutions":["Make the number of image placeholders in the prompt text exactly match len(image_data)","Verify each image item in the request maps to exactly one placeholder before submitting","Check that image_data was not truncated or duplicated upstream in your client code"],"exampleFix":"# before\nprompt = \"<|START_OF_TURN|>[image]<|END_OF_TURN|> describe\"  # 1 placeholder\nimage_data = [img1, img2]  # 2 images -> error\n# after\nprompt = \"<|START_OF_TURN|>[image][image]<|END_OF_TURN|> describe\"\nimage_data = [img1, img2]","handlingStrategy":"validation","validationCode":"placeholder_count = prompt.count(image_placeholder_token)\nassert placeholder_count == len(image_data), f\"{placeholder_count} placeholders vs {len(image_data)} images\"","typeGuard":null,"tryCatchPattern":"catch ValueError around process_mm_data_async and surface a 400 with placeholder-vs-image counts to the client","preventionTips":["Generate the prompt template from the image list length, not independently","Validate placeholder count equals image count at request-build time"],"tags":["multimodal","kimi-vl","image-input","validation"],"backgroundTag":"multimodal-placeholder-count-mismatch","analyzedSha":"0132848349585cfe6aae51c4941cbae872505f8a","analyzedAt":"2026-08-28T05:10:05.995Z","schemaVersion":2},"datasetVersion":"2026-08-28T06:17:29.519Z"}