sgl-project/sglang · error · ValueError
Kimi image placeholders must map one-to-one to image data: e
Error message
Kimi image placeholders must map one-to-one to image data: expected {expected_image_count}, found {placeholder_count} token(s) What it means
The Kimi K2.5 processor enforces a one-to-one mapping between image placeholders in the text and image_data entries. count_image_placeholders found a placeholder count different from len(image_data), so it fails before loading.
Source
Thrown at python/sglang/srt/multimodal/processors/kimi_k25.py:561
# HF processor here would silently bypass Kimi's GPU preprocessing.
super().__init__(hf_config, server_args, processor, *args, **kwargs)
self.mm_tokens = mm_tokens
async def process_mm_data_async(
self,
image_data: List[Union[str, bytes, Dict]],
input_text,
request_obj,
*args,
**kwargs,
):
expected_image_count = len(image_data or [])
placeholder_count = self.count_image_placeholders(
input_text, self.mm_tokens.image_token_id
)
if placeholder_count is not None:
if placeholder_count != expected_image_count:
raise ValueError(
"Kimi image placeholders must map one-to-one to image data: "
f"expected {expected_image_count}, found {placeholder_count} token(s)"
)
base_output = await self.fast_load_mm_data(
prompt=input_text,
image_data=image_data,
multimodal_tokens=self.mm_tokens,
# fast_load_mm_data, unlike load_mm_data, does not derive
# input_ids from the prompt; without this the wrapper falls back
# to re-tokenizing the expanded string.
input_ids=input_text,
)
else:
base_output = await self.load_mm_data(
prompt=input_text,
image_data=image_data,
multimodal_tokens=self.mm_tokens,
)View on GitHub (pinned to 0132848349)
Solutions
- Align the number of image placeholder tokens in input_text with len(image_data)
- Regenerate the prompt with the official chat template for the current image list
- If placeholders are absent by design, send no image_data
Example fix
# before
out = await proc.process_mm_data_async(
prompt=f"{IMG} compare these",
image_data=[img1, img2],
)
# after
out = await proc.process_mm_data_async(
prompt=f"{IMG} {IMG} compare these",
image_data=[img1, img2],
) Defensive patterns
Strategy: validation
Validate before calling
n = proc.count_image_placeholders(input_text, proc.mm_tokens.image_token_id)
n_img = len(image_data or [])
assert n is None or n == n_img, f"{n} placeholders vs {n_img} images" Prevention
- Always render prompts with the official chat template
- Update placeholders whenever the image list changes
- Catch ValueError and surface a 4xx-style client error, not a retryable one
When it happens
Trigger: Calling process_mm_data_async with input_text whose image placeholder token count != len(image_data) (count_image_placeholders returned non-None and mismatched).
Common situations: Client sends 3 images but the templated prompt has 2 placeholders (or vice versa), or a prompt with zero placeholders while still passing image_data.
Related errors
- The number of image placeholders exceeds img_grid_thw entrie
- The number of image placeholders does not match img_grid_thw
- Expected {len(image_token_counts)} image placeholder token(s
- Grid dim ({_mm_grid_attrs[modality]}) not found in {mm_input
- Invalid grid metadata for kimi image tokens: {vals} (expecte
AI-assisted analysis of sgl-project/sglang@0132848349 (2026-08-28).
Data as JSON: /api/errors/fc9f574fcec7cef3.
Report an issue: GitHub.