{"record":{"id":"7c0278e60d9aa648","repo":"sgl-project/sglang","slug":"action-string-is-empty","errorCode":null,"errorMessage":"action string is empty","messagePattern":"action string is empty","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"python/sglang/multimodal_gen/runtime/pipelines_core/stages/model_specific_stages/sana_wm/base.py","lineNumber":123,"sourceCode":"    allow_none: bool = False,\n    error_label: str = \"camera_actions\",\n) -> list[list[str]]:\n    if payload is None and allow_none:\n        return []\n    if not isinstance(payload, list):\n        raise ValueError(f\"{error_label} must be list[list[str]]\")\n    out: list[list[str]] = []\n    for frame_actions in payload:\n        if not isinstance(frame_actions, list):\n            raise ValueError(f\"{error_label} must be list[list[str]]\")\n        out.append([str(key).lower() for key in frame_actions])\n    return out\n\n\ndef parse_sana_wm_action_string(action: str) -> list[list[str]]:\n    cleaned = \"\".join(action.replace(\"，\", \",\").split())\n    if not cleaned:\n        raise ValueError(\"action string is empty\")\n\n    per_frame: list[list[str]] = []\n    for segment in cleaned.split(\",\"):\n        if not segment or \"-\" not in segment:\n            raise ValueError(\n                f\"invalid action segment {segment!r}; expected '<keys>-<frames>'\"\n            )\n        keys_part, duration = segment.rsplit(\"-\", 1)\n        if not duration.isdigit() or int(duration) <= 0:\n            raise ValueError(f\"invalid duration in action segment {segment!r}\")\n\n        if keys_part.lower() == \"none\":\n            keys: list[str] = []\n        else:\n            bad = sorted(\n                {\n                    char\n                    for char in keys_part.lower()","sourceCodeStart":105,"sourceCodeEnd":141,"githubUrl":"https://github.com/sgl-project/sglang/blob/0132848349585cfe6aae51c4941cbae872505f8a/python/sglang/multimodal_gen/runtime/pipelines_core/stages/model_specific_stages/sana_wm/base.py#L105-L141","documentation":"Raised by parse_sana_wm_action_string when, after removing all whitespace and normalizing full-width commas to ASCII commas, the action string is empty. The parser expects comma-separated segments like '<keys>-<frames>'.","triggerScenarios":"Calling parse_sana_wm_action_string('') , '   ', or a string of only commas/whitespace (e.g. ' , , '). Reached via on_init, ingest_event, sana_wm_action_to_camera_to_world_array, and _action_num_frames_for_request.","commonSituations":"Passing an empty camera_actions string from request config; user prompt produced no action tokens; upstream defaulted the field to '' instead of None.","solutions":["Supply a non-empty action string such as 'none-8' or 'ab-4,none-4'","Treat empty/missing action as 'none-<num_frames>' if a default is desired","Guard upstream: if not action.strip(): use default"],"exampleFix":"// before\naction = request.camera_actions or ''\n// after\naction = request.camera_actions or f'none-{num_frames}'","handlingStrategy":"fallback","validationCode":"action = (action or '').strip() or f'none-{num_frames}'","typeGuard":"def is_parseable_action(s: str) -> bool:\n    return bool(''.join(s.replace('，', ',').split()))","tryCatchPattern":null,"preventionTips":["Default missing action strings to 'none-<frames>' at the API boundary","Reject empty user-supplied action strings with a 4xx before dispatch"],"tags":["validation","action-string","sana-wm"],"backgroundTag":"empty-input-validation","analyzedSha":"0132848349585cfe6aae51c4941cbae872505f8a","analyzedAt":"2026-08-28T05:10:05.995Z","schemaVersion":2},"datasetVersion":"2026-08-28T06:17:29.519Z"}