{"record":{"id":"372ffe62b1f0163e","repo":"sgl-project/sglang","slug":"pi05-v1-expects-one-prompt-per-action-request","errorCode":null,"errorMessage":"Pi05 v1 expects one prompt per action request","messagePattern":"Pi05 v1 expects one prompt per action request","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"python/sglang/multimodal_gen/runtime/pipelines_core/stages/model_specific_stages/pi05_preprocess.py","lineNumber":155,"sourceCode":"        encoded = self.tokenizer(\n            full_prompts,\n            max_length=self.config.max_token_len,\n            padding=\"max_length\",\n            truncation=True,\n            return_tensors=\"pt\",\n        )\n        return encoded[\"input_ids\"].to(torch.long), encoded[\"attention_mask\"].to(\n            torch.bool\n        )\n\n    def __call__(self, raw_observation: dict[str, Any]) -> VLAObservationBatch:\n        prompt_value = raw_observation.get(\"prompt\", \"\")\n        if isinstance(prompt_value, list):\n            prompt = [str(x) for x in prompt_value]\n        else:\n            prompt = [str(prompt_value)]\n        if len(prompt) != 1:\n            raise ValueError(\"Pi05 v1 expects one prompt per action request\")\n\n        raw_images = raw_observation.get(\"images\") or {}\n        image_masks_in = raw_observation.get(\"image_masks\") or {}\n        camera_order = tuple(\n            raw_observation.get(\"camera_order\") or self.config.image_keys\n        )\n\n        images: dict[str, torch.Tensor] = {}\n        image_masks: dict[str, torch.Tensor] = {}\n        for key in camera_order:\n            value = raw_images.get(key)\n            is_present = value is not None and bool(image_masks_in.get(key, True))\n            if is_present:\n                tensor = _preprocess_image(value, self.config.image_size)\n            else:\n                channels = 3\n                height, width = self.config.image_size\n                tensor = torch.ones(channels, height, width, dtype=torch.float32) * -1.0","sourceCodeStart":137,"sourceCodeEnd":173,"githubUrl":"https://github.com/sgl-project/sglang/blob/0132848349585cfe6aae51c4941cbae872505f8a/python/sglang/multimodal_gen/runtime/pipelines_core/stages/model_specific_stages/pi05_preprocess.py#L137-L173","documentation":"The Pi05 v1 preprocessing stage requires exactly one text prompt per action request. The stage reads raw_observation['prompt'], stringifies it (or each element if it's a list), and rejects anything that does not reduce to a single prompt, because the downstream model invocation is built for batch size 1.","triggerScenarios":"Calling the pi05 preprocess stage with raw_observation['prompt'] being a list of length != 1, e.g. ['a','b'], or a value that stringifies to something combined with a list of 2+ items. Any multi-prompt batched request triggers it.","commonSituations":"Porting batched VLA inference code from another framework that supports multiple prompts per request; accidentally wrapping the prompt in extra list nesting; feeding a list of prompts when iterating a dataset without splitting per-sample.","solutions":["Set raw_observation['prompt'] to a single string (or a one-element list) per request.","If you need multiple prompts, split them into separate action requests and call the stage once each.","Add a pre-check in your data loader that asserts len(prompt)==1 before dispatching."],"exampleFix":"# before\nraw_observation = {\"prompt\": [\"pick up the cup\", \"stack the block\"]}\nstage(raw_observation)\n\n# after\nfor p in [\"pick up the cup\", \"stack the block\"]:\n    stage({\"prompt\": p})","handlingStrategy":"validation","validationCode":"p = raw_observation.get(\"prompt\", \"\")\nplist = p if isinstance(p, list) else [p]\nassert len(plist) == 1, f\"expected 1 prompt, got {len(plist)}\"","typeGuard":"from typing import Union\n\ndef is_single_prompt(obs: dict) -> bool:\n    p = obs.get(\"prompt\", \"\")\n    return not isinstance(p, list) or len(p) == 1","tryCatchPattern":"try:\n    out = stage(raw_observation)\nexcept ValueError as e:\n    if \"one prompt per action request\" in str(e):\n        # split and retry per-prompt\n        ...\n    raise","preventionTips":["Keep one observation dict per environment step.","Unit-test your data adapter with a two-prompt list to confirm it splits."],"tags":["pi05","vla","prompt-validation","batch-size"],"backgroundTag":"input-validation-failed","analyzedSha":"0132848349585cfe6aae51c4941cbae872505f8a","analyzedAt":"2026-08-28T05:10:05.995Z","schemaVersion":2},"datasetVersion":"2026-08-28T06:17:29.519Z"}