{"record":{"id":"43d0eaf1911b9113","repo":"sgl-project/sglang","slug":"pass-only-one-of-camera-actions-or-action","errorCode":null,"errorMessage":"pass only one of camera_actions or action","messagePattern":"pass only one of camera_actions or action","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"python/sglang/multimodal_gen/runtime/entrypoints/openai/realtime/adapters/sana_wm_realtime_adapter.py","lineNumber":136,"sourceCode":"            }\n        request.fps = int(request.fps or SANA_WM_DEFAULT_FPS)\n        request.num_inference_steps = int(\n            request.num_inference_steps or SANA_WM_DEFAULT_STEPS\n        )\n        request.guidance_scale = float(\n            request.guidance_scale or SANA_WM_DEFAULT_GUIDANCE\n        )\n        if request.negative_prompt is None:\n            request.negative_prompt = \"\"\n        if request.generator_device is None:\n            request.generator_device = \"cuda\"\n\n        state = self._state(session)\n        condition_inputs = dict(request.condition_inputs or {})\n        camera_actions = condition_inputs.pop(\"camera_actions\", None)\n        action = condition_inputs.pop(\"action\", None)\n        if camera_actions is not None and action is not None:\n            raise ValueError(\"pass only one of camera_actions or action\")\n        if camera_actions is not None:\n            state.receive_camera_control_event_payload(camera_actions, event_id=None)\n        if action is not None:\n            if not isinstance(action, str) or not action:\n                raise ValueError(\"action condition input must be a non-empty string\")\n            state.receive_camera_action_script(\n                parse_sana_wm_action_string(action), event_id=None\n            )\n        state.base_condition_inputs = condition_inputs\n\n        await save_realtime_first_frame(\n            session,\n            request,\n            required_error=\"SANA-WM realtime requires first_frame\",\n            cache_remote_urls=True,\n        )\n\n    def ingest_event(","sourceCodeStart":118,"sourceCodeEnd":154,"githubUrl":"https://github.com/sgl-project/sglang/blob/0132848349585cfe6aae51c4941cbae872505f8a/python/sglang/multimodal_gen/runtime/entrypoints/openai/realtime/adapters/sana_wm_realtime_adapter.py#L118-L154","documentation":"The SANA world-model realtime adapter's on_init rejects requests that provide BOTH camera_actions and action in condition_inputs — they are mutually exclusive control-script inputs.","triggerScenarios":"Creating a session with request.condition_inputs = {\"camera_actions\": [...], \"action\": \"turn_left\"} — both keys present and non-None.","commonSituations":"Migrating a client from one control mechanism to the other and leaving both fields set; config templates that default-fill both keys.","solutions":["Send exactly one of camera_actions (list[list[str]]) or action (non-empty string), popping the other","If both derive from one script, choose the more expressive camera_actions form","Sanitize condition_inputs client-side to remove the unused key"],"exampleFix":"// before\ncondition_inputs = {\"camera_actions\": [[\"turn_left\"]], \"action\": \"turn_left\"}\n// after\ncondition_inputs = {\"camera_actions\": [[\"turn_left\"]]}","handlingStrategy":"validation","validationCode":"ci = dict(request.condition_inputs or {})\nassert not ('camera_actions' in ci and 'action' in ci), 'mutually exclusive'","typeGuard":null,"tryCatchPattern":"except ValueError as e: if 'only one of' in str(e): pop the redundant key and retry init","preventionTips":["Send exactly one control mechanism per session","Pop unused keys from condition_inputs templates"],"tags":["realtime","mutually-exclusive","condition-inputs","sana"],"backgroundTag":"conflicting-request-parameters","analyzedSha":"0132848349585cfe6aae51c4941cbae872505f8a","analyzedAt":"2026-08-28T05:10:05.995Z","schemaVersion":2},"datasetVersion":"2026-08-28T06:17:29.519Z"}