sgl-project/sglang · error · ValueError
[internvl][qwen] image_data provided but no images parsed fr
Error message
[internvl][qwen] image_data provided but no images parsed from prompt placeholders
What it means
In the Qwen-flavored InternVL path, image_data was provided but the prompt string contained no image placeholders, so no pixel_values were ever parsed and the model would see images it cannot place. The processor scans the prompt for per-image placeholder markers (e.g. <img>...</img> or <image> tokens) and pairs each with an image; zero parsed images plus non-empty image_data triggers this raise.
Source
Thrown at python/sglang/srt/multimodal/processors/internvl.py:464
for image in base_output.images:
if isinstance(image, Image.Image):
img_np = np.array(image.convert("RGB"))
tensor = (
torch.from_numpy(img_np).permute(2, 0, 1).to(get_device()).float()
/ 255.0
)
else:
tensor = image.to(get_device())
tensor = (tensor - mean) / std
tiles = self.dynamic_preprocess(
tensor, image_size=448, max_num=img_max_num, use_thumbnail=True
)
pixel_values_list.append(tiles)
num_patches_list.append(int(tiles.shape[0]))
if image_data and not pixel_values_list:
raise ValueError(
"[internvl][qwen] image_data provided but no images parsed from prompt placeholders"
)
image_tensor = (
torch.cat(pixel_values_list, dim=0) if pixel_values_list else None
)
# ----- Videos -> frame tiles (optional) -----
video_tensor = None
video_patch_lists = []
video_pixel_values = []
requested_frames = int(
kwargs.get("video_num_frames", self.DEFAULT_VIDEO_NUM_FRAMES)
)
num_frames = self._resolve_video_num_frames(
requested=requested_frames,
num_videos=len(base_output.videos),View on GitHub (pinned to 0132848349)
Solutions
- Apply the InternVL-Qwen chat template / insert one image placeholder per image into the prompt before calling
- Match the exact placeholder syntax the processor scans for (see its regex in internvl.py)
- If images are optional for this request, don't pass image_data
Example fix
# before prompt = 'Describe this.' # no placeholder out = await proc.process_qwen_mm_data_async(image_data=[img], prompt=prompt) # after prompt = f'<image>Describe this.' # one placeholder per image out = await proc.process_qwen_mm_data_async(image_data=[img], prompt=prompt)
Defensive patterns
Strategy: validation
Validate before calling
n_ph = count_image_placeholders(prompt) # regex used by internvl processor
if image_data and n_ph == 0:
prompt = insert_image_placeholders(prompt, len(image_data))
if image_data and n_ph != len(image_data):
raise UserInputError('placeholder count must equal image count') Type guard
def prompt_has_placeholders(prompt: str, n_images: int) -> bool:
return count_image_placeholders(prompt) == n_images Try / catch
try:
out = await proc.process_qwen_mm_data_async(image_data, prompt)
except ValueError as e:
if 'no images parsed' in str(e):
prompt = f'<image>'*len(image_data) + prompt
out = await proc.process_qwen_mm_data_async(image_data, prompt)
else: raise Prevention
- Always run prompts through apply_chat_template
- Verify placeholder syntax matches the processor's parser regex
When it happens
Trigger: Calling process_qwen_mm_data_async with image_data=[...] but a prompt string lacking image placeholder markup; placeholders spelled differently than the template the parser expects; chat template not applied so placeholder tokens were never inserted.
Common situations: Building prompts manually with plain markdown  instead of the model's placeholder syntax; forgetting apply_chat_template; template version drift changing the placeholder string.
Related errors
- An exception occurred while loading multimodal data: {e}
- prompt has {num_placeholders} image placeholder token(s) but
- processor image placeholder count mismatch: processor={proce
- Image placeholder count does not match image_data
- Audio placeholder count does not match audio_data
AI-assisted analysis of sgl-project/sglang@0132848349 (2026-08-28).
Data as JSON: /api/errors/8b0c77c136ac33f2.
Report an issue: GitHub.