sgl-project/sglang · error · ValueError

Z-Image expects one caption embedding per image, got {len(al

Error message

Z-Image expects one caption embedding per image, got {len(all_image)} images and {len(all_cap_feats)} captions

What it means

Raised by ZImage.patchify_and_embed when the number of image latents in all_image differs from the number of caption embeddings in all_cap_feats. The model pairs each image with exactly one caption embedding; a length mismatch means the batch assembly is inconsistent.

Source

Thrown at python/sglang/multimodal_gen/runtime/models/dits/zimage.py:971

    def patchify_and_embed(
        self,
        all_image: List[torch.Tensor],
        all_cap_feats: List[torch.Tensor],
        patch_size: int,
        f_patch_size: int,
        image_seq_len_target: int | None = None,
        caption_valid_lens: torch.Tensor | None = None,
        caption_valid_mask: torch.Tensor | None = None,
    ):
        """Patchify images and pad image/caption tokens to batch targets.

        Each image is [C, F, H, W] and has one [L, D] caption. Returned tensors
        are stacked as [B, S, D], while valid lengths keep track of real tokens
        before learned pad tokens are restored. `image_seq_len_target`, when
        set, is the SP-local padded image-token target.
        """
        if len(all_image) != len(all_cap_feats):
            raise ValueError(
                f"Z-Image expects one caption embedding per image, got {len(all_image)} images and {len(all_cap_feats)} captions"
            )
        if not all_image:
            raise ValueError("Z-Image batch must contain at least one image latent")
        if caption_valid_mask is not None and caption_valid_mask.shape[0] != len(
            all_cap_feats
        ):
            raise ValueError("caption_valid_mask must have one row per Z-Image caption")

        pH = pW = patch_size
        pF = f_patch_size
        all_image_out = []
        all_image_size = []
        all_cap_feats_out = []
        all_image_valid_lens = []
        all_cap_valid_lens = []
        all_cap_valid_masks = []
        all_image_attn_lens = []

View on GitHub (pinned to 0132848349)

Solutions

  1. Make the batching code build (image, caption) pairs and never filter one side independently
  2. Assert len(all_image) == len(all_cap_feats) before calling forward
  3. Check upstream filtering logic that removed failed latents or captions

Example fix

# before
all_image = [img for img, ok in zip(imgs, oks) if ok]
all_cap_feats = caps  # kept all
# after
pairs = [(img, cap) for img, cap, ok in zip(imgs, caps, oks) if ok]
all_image = [p[0] for p in pairs]
all_cap_feats = [p[1] for p in pairs]
Defensive patterns

Strategy: validation

Validate before calling

assert len(all_image) == len(all_cap_feats), "image/caption count mismatch"

Type guard

def batch_pairs_aligned(images: list, caps: list) -> bool:
    return len(images) == len(caps)

Prevention

When it happens

Trigger: Calling the Z-Image forward with 2 image latents but 3 caption feature tensors (or vice versa), typically from a batching routine that zips/pads images and captions separately.

Common situations: Batching routine drops an image when its latent fails to encode but keeps the caption; mis-indexed caption list after filtering invalid samples.

Related errors


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