sgl-project/sglang · error · ValueError
Expected {len(image_token_counts)} image placeholder(s), fou
Error message
Expected {len(image_token_counts)} image placeholder(s), found {len(parts) - 1}. What it means
Raised by _expand_k3_image_prompt_text (the CPU HF-processor fallback path) when splitting the raw prompt text on the image token string does not yield exactly one segment boundary per expected image. The text path must mirror the token-id path, so counts must agree before expansion.
Source
Thrown at python/sglang/srt/multimodal/processors/kimi_k3.py:133
)
)
output.extend([image_token_id] * image_token_counts[image_index])
output.extend(_encode_k3_special_tokens(tokenizer, "<|media_end|>"))
image_index += 1
return torch.tensor(output, dtype=torch.long).unsqueeze(0)
def _expand_k3_image_prompt_text(
input_text: str,
image_token: str,
image_token_counts: List[int],
image_sizes: List[tuple[int, int]],
) -> str:
"""Render the K3 media framing for the CPU HF-processor fallback."""
parts = input_text.split(image_token)
if len(parts) - 1 != len(image_token_counts):
raise ValueError(
f"Expected {len(image_token_counts)} image placeholder(s), "
f"found {len(parts) - 1}."
)
output = [parts[0]]
for image_token_count, (width, height), suffix in zip(
image_token_counts, image_sizes, parts[1:]
):
output.extend(
(
f"<|media_begin|>image {width}x{height}<|media_content|>",
image_token * image_token_count,
"<|media_end|>",
suffix,
)
)
return "".join(output)
View on GitHub (pinned to 0132848349)
Solutions
- Ensure the prompt text embeds exactly one image_token string per image
- Confirm the image_token passed matches the model's configured placeholder token
- Avoid hand-building the media-framing text; use the model's chat template
Example fix
# before text = "<image> describe" * 1 # wrong placeholder literal expand(text, image_token="<|IMAGE_TOKEN|>", counts=[c1, c2]) # after text = "<|IMAGE_TOKEN|><|IMAGE_TOKEN|> describe" expand(text, image_token="<|IMAGE_TOKEN|>", counts=[c1, c2])
Defensive patterns
Strategy: validation
Validate before calling
def check_text(text, image_token, counts):
n = text.split(image_token).__len__() - 1
assert n == len(counts), f"{n} placeholders vs {len(counts)} images" Prevention
- Use the model chat template to render media framing
- Keep the image_token string in sync with model config
When it happens
Trigger: Running the CPU fallback (_cpu_call path) where input_text.split(image_token) produces len(parts)-1 != len(image_token_counts), e.g. text uses a different placeholder string than mm_tokens.image_token, or extra/missing placeholders.
Common situations: Chat template renders a placeholder literal different from the configured image token; manually concatenated prompt text; version change of the image token string.
Related errors
- Kimi-K3 encoder mode supports image input only
- Expected {len(image_token_counts)} image placeholder token(s
- Z-Image text embeddings must have shape [seq, dim] or [batch
- f"Unsupported patch_size type: {type(patch_size)}"
- f"Expected camera embedding shape [B, C, F, H, W], got {tupl
AI-assisted analysis of sgl-project/sglang@0132848349 (2026-08-28).
Data as JSON: /api/errors/4562746d9d4e8613.
Report an issue: GitHub.