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

  1. Apply the InternVL-Qwen chat template / insert one image placeholder per image into the prompt before calling
  2. Match the exact placeholder syntax the processor scans for (see its regex in internvl.py)
  3. 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

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 ![img](...) instead of the model's placeholder syntax; forgetting apply_chat_template; template version drift changing the placeholder string.

Related errors


AI-assisted analysis of sgl-project/sglang@0132848349 (2026-08-28). Data as JSON: /api/errors/8b0c77c136ac33f2. Report an issue: GitHub.