sgl-project/sglang · error · ValueError

Invalid modality: {modality}

Error message

Invalid modality: {modality}

What it means

Raised by MMReceiver._set_part_grid when the modality passed in is not a key in _MODALITY_GRID_ATTRS (which only maps IMAGE, VIDEO, AUDIO to their grid attribute names). It guards against writing grid data into an attribute that does not exist for the part being assembled.

Source

Thrown at python/sglang/srt/disaggregation/encoder/receiver.py:590

            self._set_video_meta_for_part(part_idx, kwargs)
        if modality == Modality.IMAGE:
            self._set_image_meta_for_part(part_idx, kwargs)

    def _set_image_meta_for_part(self, part_idx, source):
        for attr_name in _GENERAL_IMAGE_META_ATTRS:
            val = (
                source.get(attr_name)
                if isinstance(source, dict)
                else getattr(source, attr_name, None)
            )
            if val is not None:
                getattr(self, attr_name)[part_idx] = val

    def _set_part_grid(self, part_idx, modality, grid):
        """Set the grid for one part according to modality (IMAGE/VIDEO/AUDIO)."""
        spec = _MODALITY_GRID_ATTRS.get(modality)
        if spec is None:
            raise ValueError(f"Invalid modality: {modality}")
        attr_name, flatten = spec
        value = grid.flatten() if flatten else grid
        getattr(self, attr_name)[part_idx] = value

    def _set_video_meta_for_part(self, part_idx, source):
        """Copy video_timestamps and second_per_grid_ts from source (dict or object)."""
        for attr_name in self.video_meta_attrs:
            val = (
                source.get(attr_name)
                if isinstance(source, dict)
                else getattr(source, attr_name, None)
            )
            if val is not None:
                getattr(self, attr_name)[part_idx] = val

    @classmethod
    def from_embedding_data(
        cls,

View on GitHub (pinned to 0132848349)

Solutions

  1. Coerce the value to the Modality enum before calling (e.g. Modality(modality) or a mapping table for legacy string values).
  2. If adding a new modality, add its (attr_name, flatten) entry to _MODALITY_GRID_ATTRS.
  3. Log/inspect the incoming modality value to find where a raw string or None slips through.

Example fix

# before
receiver._set_part_grid(idx, part.modality, grid)  # part.modality is "image"
# after
receiver._set_part_grid(idx, Modality(part.modality.upper()), grid)
Defensive patterns

Strategy: validation

Validate before calling

from sglang.srt.disaggregation.encoder.receiver import _MODALITY_GRID_ATTRS

def is_supported_modality(modality) -> bool:
    return modality in _MODALITY_GRID_ATTRS

assert is_supported_modality(part.modality), f"unsupported modality: {part.modality!r}"

Type guard

def is_valid_modality(m) -> bool:
    from sglang.srt.multimodal import Modality  # adjust import as needed
    return isinstance(m, Modality) and m in (Modality.IMAGE, Modality.VIDEO, Modality.AUDIO)

Try / catch

try:
    receiver._set_part_grid(idx, modality, grid)
except ValueError:
    logger.warning("dropping part with unknown modality %r", modality)

Prevention

When it happens

Trigger: Calling the receiver's part-grid setter (from __init__ or add) with a modality value that is not Modality.IMAGE/VIDEO/AUDIO — e.g. a raw string like "image" vs the enum, None, or a newly added modality that lacks a mapping in _MODALITY_GRID_ATTRS.

Common situations: Deserializing grid metadata where modality arrived as a lowercase string instead of the Modality enum; extending the modality set without updating _MODALITY_GRID_ATTRS; corrupted/malformed payloads from an older encoder version.

Understand the failure class

Background: Invalid enum value errors: "Unknown type", "Invalid scope", "must be one of" — when a string is not on the library's allowed list — this error's family across 23 libraries.

Related errors


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