{"record":{"id":"7022e34a8e6d2e1d","repo":"sgl-project/sglang","slug":"cosmos3-forward-dynamics-produces-video-use-v1-v","errorCode":null,"errorMessage":"Cosmos3 forward_dynamics produces video; use /v1/videos instead","messagePattern":"Cosmos3 forward_dynamics produces video; use /v1/videos instead","errorType":"validation","errorClass":"ValueError","httpStatus":400,"severity":"error","filePath":"python/sglang/multimodal_gen/runtime/entrypoints/action/cosmos3.py","lineNumber":137,"sourceCode":"    if len(prompts) != batch_size:\n        raise ValueError(\n            \"Cosmos3 batched action input requires one prompt per image, got \"\n            f\"{len(prompts)} prompt(s) and {batch_size} image(s)\"\n        )\n    return prompts[0] if batch_size == 1 else prompts\n\n\ndef build_cosmos3_action_sampling_params(\n    payload: dict[str, Any],\n    observation: dict[str, Any],\n    server_args: ServerArgs,\n    sampling_params_cls: type[Cosmos3SamplingParams],\n) -> Cosmos3SamplingParams:\n    parameters = dict(payload.get(\"parameters\") or {})\n    options = {**observation, **parameters}\n    action_mode = str(options.get(\"action_mode\", \"policy\")).strip().lower()\n    if action_mode == \"forward_dynamics\":\n        raise ValueError(\n            \"Cosmos3 forward_dynamics produces video; use /v1/videos instead\"\n        )\n    if action_mode not in (\"policy\", \"inverse_dynamics\"):\n        raise ValueError(\n            \"Cosmos3 action endpoint supports action_mode='policy' or \"\n            \"'inverse_dynamics'\"\n        )\n\n    action_horizon = options.get(\"action_horizon\")\n    num_frames = options.get(\"num_frames\")\n    if action_horizon is None and num_frames is None:\n        action_horizon = 16\n    if action_horizon is not None:\n        action_horizon = int(action_horizon)\n        if action_horizon <= 0:\n            raise ValueError(\"action_horizon must be a positive integer\")\n        expected_num_frames = action_horizon + 1\n        if num_frames is not None and int(num_frames) != expected_num_frames:","sourceCodeStart":119,"sourceCodeEnd":155,"githubUrl":"https://github.com/sgl-project/sglang/blob/0132848349585cfe6aae51c4941cbae872505f8a/python/sglang/multimodal_gen/runtime/entrypoints/action/cosmos3.py#L119-L155","documentation":"Cosmos3's forward_dynamics mode generates video frames, not actions, so it is explicitly rejected on the /v1/actions endpoint. The builder checks the action_mode option (merged from observation and parameters) and routes forward_dynamics users to /v1/videos. This prevents a guaranteed downstream failure/inappropriate response format.","triggerScenarios":"POST to the action endpoint with parameters.action_mode='forward_dynamics' or observation.action_mode='forward_dynamics' (any case/whitespace variant).","commonSituations":"Reusing a video-generation client config against the action endpoint; copy-pasting from Cosmos3 docs where forward_dynamics is the default video mode; exploratory calls switching action_mode values.","solutions":["Use the /v1/videos endpoint for forward_dynamics requests","Switch action_mode to 'policy' or 'inverse_dynamics' if you actually want actions"],"exampleFix":"# before\nPOST /v1/actions {\"parameters\": {\"action_mode\": \"forward_dynamics\"}}\n# after\nPOST /v1/videos {\"parameters\": {\"action_mode\": \"forward_dynamics\"}}","handlingStrategy":"validation","validationCode":"if str(params.get('action_mode','policy')).strip().lower() == 'forward_dynamics':\n    target = '/v1/videos'  # route there instead of /v1/actions","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Keep separate client functions per endpoint (actions vs videos)","Check action_mode before choosing the endpoint"],"tags":["cosmos3","action-mode","endpoint-routing","video-generation"],"backgroundTag":"wrong-endpoint-for-mode","analyzedSha":"0132848349585cfe6aae51c4941cbae872505f8a","analyzedAt":"2026-08-28T05:10:05.995Z","schemaVersion":2},"datasetVersion":"2026-08-28T06:17:29.519Z"}