sgl-project/sglang · error · ValueError

pass only one of camera_actions or action

Error message

pass only one of camera_actions or action

What it means

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.

Source

Thrown at python/sglang/multimodal_gen/runtime/entrypoints/openai/realtime/adapters/sana_wm_realtime_adapter.py:136

            }
        request.fps = int(request.fps or SANA_WM_DEFAULT_FPS)
        request.num_inference_steps = int(
            request.num_inference_steps or SANA_WM_DEFAULT_STEPS
        )
        request.guidance_scale = float(
            request.guidance_scale or SANA_WM_DEFAULT_GUIDANCE
        )
        if request.negative_prompt is None:
            request.negative_prompt = ""
        if request.generator_device is None:
            request.generator_device = "cuda"

        state = self._state(session)
        condition_inputs = dict(request.condition_inputs or {})
        camera_actions = condition_inputs.pop("camera_actions", None)
        action = condition_inputs.pop("action", None)
        if camera_actions is not None and action is not None:
            raise ValueError("pass only one of camera_actions or action")
        if camera_actions is not None:
            state.receive_camera_control_event_payload(camera_actions, event_id=None)
        if action is not None:
            if not isinstance(action, str) or not action:
                raise ValueError("action condition input must be a non-empty string")
            state.receive_camera_action_script(
                parse_sana_wm_action_string(action), event_id=None
            )
        state.base_condition_inputs = condition_inputs

        await save_realtime_first_frame(
            session,
            request,
            required_error="SANA-WM realtime requires first_frame",
            cache_remote_urls=True,
        )

    def ingest_event(

View on GitHub (pinned to 0132848349)

Solutions

  1. Send exactly one of camera_actions (list[list[str]]) or action (non-empty string), popping the other
  2. If both derive from one script, choose the more expressive camera_actions form
  3. Sanitize condition_inputs client-side to remove the unused key

Example fix

// before
condition_inputs = {"camera_actions": [["turn_left"]], "action": "turn_left"}
// after
condition_inputs = {"camera_actions": [["turn_left"]]}
Defensive patterns

Strategy: validation

Validate before calling

ci = dict(request.condition_inputs or {})
assert not ('camera_actions' in ci and 'action' in ci), 'mutually exclusive'

Try / catch

except ValueError as e: if 'only one of' in str(e): pop the redundant key and retry init

Prevention

When it happens

Trigger: Creating a session with request.condition_inputs = {"camera_actions": [...], "action": "turn_left"} — both keys present and non-None.

Common situations: Migrating a client from one control mechanism to the other and leaving both fields set; config templates that default-fill both keys.

Related errors


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