{"record":{"id":"fd8c4f9297268e74","repo":"sgl-project/sglang","slug":"cosmos3-action-num-frames-must-be-greater-than-1","errorCode":null,"errorMessage":"Cosmos3 action num_frames must be greater than 1","messagePattern":"Cosmos3 action num_frames must be greater than 1","errorType":"validation","errorClass":"ValueError","httpStatus":400,"severity":"error","filePath":"python/sglang/multimodal_gen/runtime/entrypoints/action/cosmos3.py","lineNumber":164,"sourceCode":"    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:\n            raise ValueError(\n                \"Cosmos3 requires num_frames == action_horizon + 1, got \"\n                f\"num_frames={num_frames}, action_horizon={action_horizon}\"\n            )\n        num_frames = expected_num_frames\n    else:\n        num_frames = int(num_frames)\n        if num_frames <= 1:\n            raise ValueError(\"Cosmos3 action num_frames must be greater than 1\")\n    if (num_frames - 1) % 4 != 0:\n        raise ValueError(\n            \"Cosmos3 action_horizon must be divisible by 4 so num_frames \"\n            \"is compatible with the temporal VAE\"\n        )\n\n    images = _images_from_observation(observation)\n    video_path = options.get(\"video_path\") or observation.get(\"video\")\n    if action_mode == \"policy\" and not images:\n        raise ValueError(\"Cosmos3 policy input requires an observation image\")\n    if action_mode == \"inverse_dynamics\" and video_path is None:\n        raise ValueError(\"Cosmos3 inverse_dynamics input requires an observation video\")\n    if images and video_path is not None:\n        raise ValueError(\"Cosmos3 action requests accept either an image or a video\")\n    batch_size = len(images) if images else 1\n    max_batch_size = max(1, int(getattr(server_args, \"batching_max_size\", 1)))\n    if batch_size > max_batch_size:\n        raise ValueError(","sourceCodeStart":146,"sourceCodeEnd":182,"githubUrl":"https://github.com/sgl-project/sglang/blob/0132848349585cfe6aae51c4941cbae872505f8a/python/sglang/multimodal_gen/runtime/entrypoints/action/cosmos3.py#L146-L182","documentation":"When only num_frames is provided to the Cosmos3 action endpoint (no action_horizon), it must be > 1. num_frames represents conditioning frame + generated frames, so num_frames <= 1 leaves no room for any action. The value is int()-coerced before the check.","triggerScenarios":"Passing parameters.num_frames=1 or 0 (or negative) without an action_horizon in a /v1/actions request.","commonSituations":"Reusing a single-image inference config where num_frames=1; off-by-one confusion treating num_frames as action count; defaults meant for image endpoints.","solutions":["Set num_frames to action_horizon + 1 (e.g. 17 for horizon 16), or use action_horizon instead","For image-only policy queries, you still need num_frames/action_horizon compatible with the temporal VAE: (num_frames-1) % 4 == 0"],"exampleFix":"# before\n{\"parameters\": {\"num_frames\": 1}}\n# after\n{\"parameters\": {\"num_frames\": 17}}","handlingStrategy":"validation","validationCode":"nf = params.get('num_frames')\nif nf is not None and 'action_horizon' not in params:\n    assert int(nf) > 1, 'num_frames must be > 1'","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Prefer action_horizon over num_frames for action requests","Use num_frames values like 5, 9, 13, 17"],"tags":["cosmos3","num-frames","numeric-validation"],"backgroundTag":"invalid-parameter-range","analyzedSha":"0132848349585cfe6aae51c4941cbae872505f8a","analyzedAt":"2026-08-28T05:10:05.995Z","schemaVersion":2},"datasetVersion":"2026-08-28T06:17:29.519Z"}