{"record":{"id":"6103f65cb1eaf3e9","repo":"sgl-project/sglang","slug":"the-number-of-image-placeholders-does-not-match-im","errorCode":null,"errorMessage":"The number of image placeholders does not match img_grid_thw entries.","messagePattern":"The number of image placeholders does not match img_grid_thw entries\\.","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"python/sglang/srt/multimodal/processors/kimi_common.py","lineNumber":121,"sourceCode":"\n        for token in prompt:\n            if token != image_token_id:\n                input_ids.append(token)\n                continue\n\n            if img_idx >= len(image_token_counts):\n                raise ValueError(\n                    \"The number of image placeholders exceeds img_grid_thw entries.\"\n                )\n\n            num_tokens = image_token_counts[img_idx]\n            start = len(input_ids)\n            input_ids.extend([image_token_id] * num_tokens)\n            offsets.append((start, len(input_ids) - 1))\n            img_idx += 1\n\n        if img_idx != len(image_token_counts):\n            raise ValueError(\n                \"The number of image placeholders does not match img_grid_thw entries.\"\n            )\n\n        image_embeddings = embeddings[Modality.IMAGE]\n        mm_items = []\n        consumed = 0\n        for start, end in offsets:\n            num_tokens = end - start + 1\n            embedding_slice = image_embeddings[consumed : consumed + num_tokens]\n            consumed += num_tokens\n            mm_items.append(\n                MultimodalDataItem(\n                    modality=Modality.IMAGE,\n                    offsets=[(start, end)],\n                    precomputed_embeddings=embedding_slice,\n                )\n            )\n","sourceCodeStart":103,"sourceCodeEnd":139,"githubUrl":"https://github.com/sgl-project/sglang/blob/0132848349585cfe6aae51c4941cbae872505f8a/python/sglang/srt/multimodal/processors/kimi_common.py#L103-L139","documentation":"The Kimi placeholder-expansion loop finished but consumed fewer placeholders than the number of grid-derived image token counts: img_idx != len(image_token_counts). This is the mirror of the exceeds case — the prompt has fewer image_token_id tokens than images/grids supplied.","triggerScenarios":"Calling get_mm_data / _build_kimi_mm_data_from_grids with a prompt containing fewer image placeholder tokens than img_grid_thw entries (extra images passed but no placeholders for them).","commonSituations":"Sending multiple images with a template that only emits one placeholder, dropping placeholder tokens during custom prompt assembly, or images appended to image_data without updating the prompt.","solutions":["Ensure exactly one image placeholder token per image in the prompt","If images were removed, also remove their grid entries so counts align","Pre-validate: count of image_token_id in input_ids == len(image_token_counts) before calling"],"exampleFix":"// before\nprompt = f\"{IMG} look\"  # 1 placeholder\nbuild_from_grids(prompt, grids=[g1, g2])  # 2 images\n\n// after\nprompt = f\"{IMG} {IMG} look\"  # 2 placeholders, 2 images\nbuild_from_grids(prompt, grids=[g1, g2])","handlingStrategy":"validation","validationCode":"n_ph = sum(1 for t in input_ids if t == image_token_id)\nassert n_ph == len(image_token_counts), f\"{n_ph} placeholders != {len(image_token_counts)} grids\"","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Treat (prompt, images, grids) as one immutable request tuple","Regenerate all three when any image is added or dropped","Add an equality assert before every call"],"tags":["kimi","multimodal","placeholder-count","validation"],"backgroundTag":"multimodal-placeholder-mismatch","analyzedSha":"0132848349585cfe6aae51c4941cbae872505f8a","analyzedAt":"2026-08-28T05:10:05.995Z","schemaVersion":2},"datasetVersion":"2026-08-28T06:17:29.519Z"}