sgl-project/sglang · error · ValueError
{name} placeholder/data mismatch: {placeholder_count} placeh
Error message
{name} placeholder/data mismatch: {placeholder_count} placeholders vs {data_count} {name}s What it means
Raised by _validate_placeholder_counts when the number of multimodal placeholder tokens embedded in the prompt text doesn't equal the number of supplied data items per modality (image, video, audio counted separately). It guards the text-template vs payload consistency of the request.
Source
Thrown at python/sglang/srt/multimodal/processors/mimo_v2.py:1521
counts = {
Modality.IMAGE: 0,
Modality.VIDEO: 0,
Modality.AUDIO: 0,
}
for text_part in text_parts:
if multimodal_tokens_pattern.match(text_part):
modality = self.mm_tokens.get_modality_of_token(text_part)
if modality in counts:
counts[modality] += 1
for modality, name, data_count in (
(Modality.IMAGE, "image", image_count),
(Modality.VIDEO, "video", video_count),
(Modality.AUDIO, "audio", audio_count),
):
placeholder_count = counts[modality]
if placeholder_count != data_count:
raise ValueError(
f"{name} placeholder/data mismatch: "
f"{placeholder_count} placeholders vs {data_count} {name}s"
)
def __init__(self, hf_config, server_args, _processor, *args, **kwargs):
super().__init__(hf_config, server_args, _processor, *args, **kwargs)
self.vision_config = Qwen2_5_VLVisionConfig.from_dict(hf_config.vision_config)
patch_size = self.vision_config.patch_size
spatial_merge_size = getattr(self.vision_config, "spatial_merge_size", 2)
unit_size = patch_size * spatial_merge_size
self.image_factor = unit_size
rope_type = "rope"
rope_scaling = getattr(hf_config, "rope_scaling", None)
if rope_scaling:
if (
rope_scaling.get("type", None) == "default"View on GitHub (pinned to 0132848349)
Solutions
- Make placeholders and data lists generated from the same source: text = template.format per item, images=[...] of equal length
- Count tokens per modality before submit and assert equality client-side
- For video-with-audio, account for audio placeholders exactly as the model template expects
Example fix
# before text = '<|image|><|image|><|image|> describe' images = [img1, img2] # 3 placeholders vs 2 images → ValueError # after text = '<|image|>' * len(images) + ' describe' images = [img1, img2]
Defensive patterns
Strategy: validation
Validate before calling
import re
from collections import Counter
def check(prompt, images=0, videos=0, audios=0):
c = Counter(re.findall(r'<\|image\|>', prompt))['<|image|>'] if images else 0
# count each modality's placeholder token and compare:
assert prompt.count(IMAGE_TOKEN) == images, f'{prompt.count(IMAGE_TOKEN)} vs {images}'
assert prompt.count(VIDEO_TOKEN) == videos
assert prompt.count(AUDIO_TOKEN) == audios
check(text, images=len(images), videos=len(videos), audios=len(audios)) Try / catch
try:
out = await epd.process_mm_data_async(text, images=images, videos=videos, audios=audios)
except ValueError as e:
if 'placeholder/data mismatch' in str(e):
return error_response(400, str(e) + '; regenerate prompt from attachments')
raise Prevention
- Generate placeholder tokens programmatically: prompt = TOK * len(items) + question
- Never hand-edit multimodal prompts
- Add a client-side count assertion before every submit
When it happens
Trigger: Sending a prompt with, say, 3 <|image|> placeholders but only 2 image entries in images=[...]; or 1 video placeholder with 2 videos; likewise for audio. Any per-modality count mismatch between text template and data list triggers it.
Common situations: Templating bugs where the placeholder loop count drifts from the attachments list; client code appending images without adding tokens (or vice versa); copy-pasting prompts with leftover placeholders; audio placeholders missing when sending video-with-audio.
Related errors
- 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
- batching config rule requires max_batch_size
- {path}.kind must be a non-empty string
AI-assisted analysis of sgl-project/sglang@0132848349 (2026-08-28).
Data as JSON: /api/errors/0f8b56791fae6c1b.
Report an issue: GitHub.