{"record":{"id":"14ea0d1137645680","repo":"sgl-project/sglang","slug":"cosmos3-accepts-either-image-path-i2v-or-vid","errorCode":null,"errorMessage":"Cosmos3 accepts either --image-path (I2V) or --video-path (V2V), not both","messagePattern":"Cosmos3 accepts either --image-path \\(I2V\\) or --video-path \\(V2V\\), not both","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"python/sglang/multimodal_gen/runtime/pipelines_core/stages/model_specific_stages/cosmos3.py","lineNumber":171,"sourceCode":"\n    def verify_input(self, batch: Req, server_args: ServerArgs) -> VerificationResult:\n        return VerificationResult()\n\n    def forward(self, batch: Req, server_args: ServerArgs) -> Req:\n        image_path = batch.image_path\n        video_path = batch.video_path\n        is_action_policy = (\n            batch.data_type == DataType.ACTION\n            and getattr(batch.sampling_params, \"action_mode\", None)\n            == ACTION_MODE_POLICY\n        )\n        if isinstance(image_path, list) and not is_action_policy:\n            image_path = image_path[0] if image_path else None\n        if isinstance(video_path, list):\n            video_path = video_path[0] if video_path else None\n\n        if image_path and video_path:\n            raise ValueError(\n                \"Cosmos3 accepts either --image-path (I2V) or --video-path \"\n                \"(V2V), not both\"\n            )\n\n        target_h, target_w = batch.height, batch.width\n\n        if image_path is not None:\n            image_sources = (\n                list(image_path)\n                if isinstance(image_path, (list, tuple))\n                else [image_path]\n            )\n            if not image_sources:\n                raise ValueError(\"Cosmos3 I2V image list is empty\")\n            tensors: list[torch.Tensor] = []\n            for src in image_sources:\n                image = load_image(src)\n                image = _resize_crop_pil(image, target_w, target_h)","sourceCodeStart":153,"sourceCodeEnd":189,"githubUrl":"https://github.com/sgl-project/sglang/blob/0132848349585cfe6aae51c4941cbae872505f8a/python/sglang/multimodal_gen/runtime/pipelines_core/stages/model_specific_stages/cosmos3.py#L153-L189","documentation":"The Cosmos3 stage accepts exactly one conditioning modality: an image for image-to-video (I2V) or a video for video-to-video (V2V). Supplying both image_path and video_path is ambiguous, so the stage rejects the request up front.","triggerScenarios":"A request where both image_path and video_path resolve to truthy values after list-normalization (each list is reduced to its first element) in Cosmos3 preprocessing — e.g. a client template that always populates both fields.","commonSituations":"A generic multimodal client that sets both image and video placeholders; stale request payloads from a previous experiment; passing a video with a thumbnail/first-frame image expecting them to be combined.","solutions":["Send only image_path for I2V, or only video_path for V2V","In shared client code, gate the fields: set video_path=None when doing I2V and vice versa","Add a client-side assert that at most one of the two is non-None"],"exampleFix":"# before\nreq = {\"image_path\": \"cat.jpg\", \"video_path\": \"cat.mp4\", \"prompt\": \"...\"}\n# after\nreq = {\"image_path\": \"cat.jpg\", \"video_path\": None, \"prompt\": \"...\"}  # I2V","handlingStrategy":"validation","validationCode":"assert not (req.get(\"image_path\") and req.get(\"video_path\")), \"pass image_path XOR video_path\"","typeGuard":"def single_conditioning(req) -> bool:\n    return bool(req.get(\"image_path\")) != bool(req.get(\"video_path\"))","tryCatchPattern":null,"preventionTips":["Client templates should null out the unused modality field"],"tags":["cosmos3","i2v","v2v","mutually-exclusive","conditioning"],"backgroundTag":"mutually-exclusive-parameters","analyzedSha":"0132848349585cfe6aae51c4941cbae872505f8a","analyzedAt":"2026-08-28T05:10:05.995Z","schemaVersion":2},"datasetVersion":"2026-08-28T06:17:29.519Z"}