sgl-project/sglang · error · ValueError
Expected image placeholder(s), found .
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.
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
- Expected image placeholder token(s), found .
- Kimi-K3 encoder mode supports image input only
- batching config rule requires max_batch_size
- CUDA VMM feature transport requires each feature field to…
- Expected one Kimi-K3 image span for each image
AI-assisted analysis of sgl-project/sglang@0132848349 (2026-08-28).
Data as JSON: /api/errors/4562746d9d4e8613.
Report an issue: GitHub.
Appendix: 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)