{"record":{"id":"67a801b93b49ba3a","repo":"sgl-project/sglang","slug":"kind-state-payload-requires-transitions","errorCode":null,"errorMessage":"{kind} state payload requires transitions","messagePattern":"(.+?) state payload requires transitions","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"python/sglang/multimodal_gen/runtime/realtime/control_signals.py","lineNumber":120,"sourceCode":"                normalize_state_payload=normalize_state_payload,\n            ),\n        )\n    return ParsedControlEventPayload(\n        mode=\"script\",\n        payload=validate_script_payload(payload),\n    )\n\n\ndef _control_state_transitions_from_event_payload(\n    payload: dict[str, Any],\n    *,\n    event_id: int | None,\n    kind: str,\n    normalize_state_payload: ControlStatePayloadNormalizer,\n) -> list[ControlStateTransition]:\n    transitions = payload.get(\"transitions\")\n    if not isinstance(transitions, list):\n        raise ValueError(f\"{kind} state payload requires transitions\")\n    result = []\n    for transition in transitions:\n        if not isinstance(transition, dict):\n            raise ValueError(f\"{kind} transition must be a map\")\n        actions = transition.get(\"actions\")\n        if not isinstance(actions, list):\n            raise ValueError(f\"{kind} transition actions must be a list\")\n        timestamp_ms = transition.get(\"client_ts_ms\")\n        if timestamp_ms is not None:\n            timestamp_ms = int(timestamp_ms)\n        result.append(\n            ControlStateTransition(\n                payload=normalize_state_payload(actions),\n                seq_id=event_id,\n                timestamp_ms=timestamp_ms,\n            )\n        )\n    return result","sourceCodeStart":102,"sourceCodeEnd":138,"githubUrl":"https://github.com/sgl-project/sglang/blob/0132848349585cfe6aae51c4941cbae872505f8a/python/sglang/multimodal_gen/runtime/realtime/control_signals.py#L102-L138","documentation":"Raised by _control_state_transitions_from_event_payload when parsing a realtime control event: the payload for a control-state event kind must contain a 'transitions' key whose value is a JSON list. Missing, null, or non-list transitions are rejected.","triggerScenarios":"parse_control_event_payload receiving an event whose payload has no 'transitions' key, has transitions=null, or transitions as a dict/string.","commonSituations":"Client sending a malformed control event; schema drift between client and server on the realtime control protocol; JSON built with the wrong payload key ('states' instead of 'transitions').","solutions":["Include payload: {\"transitions\": [...]} in the event","Validate the event JSON against the control-event schema before sending"],"exampleFix":"// before\n{\"type\": \"control\", \"payload\": {\"state\": \"on\"}}\n// after\n{\"type\": \"control\", \"payload\": {\"transitions\": [{\"actions\": [\"mute\"], \"client_ts_ms\": 123}]}}","handlingStrategy":"validation","validationCode":"assert isinstance(event.get(\"payload\", {}).get(\"transitions\"), list), \"transitions must be a list\"","typeGuard":"def has_valid_transitions(payload: dict) -> bool:\n    return isinstance(payload.get(\"transitions\"), list)","tryCatchPattern":null,"preventionTips":["Generate control events with a typed builder/schema (pydantic/dataclass) instead of raw dicts","Validate outbound events against the protocol schema in tests"],"tags":["realtime","control-events","schema","validation"],"backgroundTag":"schema-validation-failed","analyzedSha":"0132848349585cfe6aae51c4941cbae872505f8a","analyzedAt":"2026-08-28T05:10:05.995Z","schemaVersion":2},"datasetVersion":"2026-08-28T06:17:29.519Z"}