sgl-project/sglang · error · ValueError

{kind} transition must be a map

Error message

{kind} transition must be a map

What it means

Raised while parsing a realtime control event's transitions list: each element of 'transitions' must be a JSON object (map), e.g. {'actions': [...], 'client_ts_ms': ...}. A bare string, number, list, or null element triggers this.

Source

Thrown at python/sglang/multimodal_gen/runtime/realtime/control_signals.py:124

        mode="script",
        payload=validate_script_payload(payload),
    )


def _control_state_transitions_from_event_payload(
    payload: dict[str, Any],
    *,
    event_id: int | None,
    kind: str,
    normalize_state_payload: ControlStatePayloadNormalizer,
) -> list[ControlStateTransition]:
    transitions = payload.get("transitions")
    if not isinstance(transitions, list):
        raise ValueError(f"{kind} state payload requires transitions")
    result = []
    for transition in transitions:
        if not isinstance(transition, dict):
            raise ValueError(f"{kind} transition must be a map")
        actions = transition.get("actions")
        if not isinstance(actions, list):
            raise ValueError(f"{kind} transition actions must be a list")
        timestamp_ms = transition.get("client_ts_ms")
        if timestamp_ms is not None:
            timestamp_ms = int(timestamp_ms)
        result.append(
            ControlStateTransition(
                payload=normalize_state_payload(actions),
                seq_id=event_id,
                timestamp_ms=timestamp_ms,
            )
        )
    return result


class ControlSignalQueue:
    """FIFO storage for discrete realtime control signals

View on GitHub (pinned to 0132848349)

Solutions

  1. Wrap each transition in an object with an 'actions' list
  2. Validate each transitions[i] is a dict before sending

Example fix

// before
{"transitions": ["mute", "unmute"]}
// after
{"transitions": [{"actions": ["mute"]}, {"actions": ["unmute"]}]}
Defensive patterns

Strategy: validation

Validate before calling

assert all(isinstance(t, dict) and isinstance(t.get("actions"), list) for t in transitions)

Type guard

def transitions_valid(transitions: list) -> bool:
    return all(isinstance(t, dict) for t in transitions)

Prevention

When it happens

Trigger: parse_control_event_payload with transitions like ["mute"] or [["mute"]] instead of [{"actions": ["mute"]}].

Common situations: Clients abbreviating transitions to plain action strings; mismatched protocol versions where transitions were previously strings.

Understand the failure class

Background: Schema validation failed / invalid input schema: payload rejected because its shape doesn't match the expected schema — this error's family across 28 libraries.

Related errors


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