{"record":{"id":"d659fe9891e2ae68","repo":"sgl-project/sglang","slug":"pi05-v1-expects-one-state-vector-per-request","errorCode":null,"errorMessage":"Pi05 v1 expects one state vector per request","messagePattern":"Pi05 v1 expects one state vector per 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":185,"sourceCode":"            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\n\n            images[key] = tensor.unsqueeze(0)\n            image_masks[key] = torch.tensor([is_present], dtype=torch.bool)\n\n        state = raw_observation.get(\"state\")\n        state_tensor = None\n        if state is not None:\n            state_tensor = torch.as_tensor(state, dtype=torch.float32)\n            if state_tensor.ndim == 1:\n                state_tensor = state_tensor.unsqueeze(0)\n            if state_tensor.shape[0] != 1:\n                raise ValueError(\"Pi05 v1 expects one state vector per request\")\n            if state_tensor.shape[-1] > self.config.state_dim:\n                raise ValueError(\n                    f\"Pi05 state dim must be <= {self.config.state_dim}, \"\n                    f\"got {state_tensor.shape[-1]}\"\n                )\n\n        noise = raw_observation.get(\"noise\")\n        noise_tensor = None\n        if noise is not None:\n            noise_tensor = torch.as_tensor(noise, dtype=torch.float32)\n            if noise_tensor.ndim == 2:\n                noise_tensor = noise_tensor.unsqueeze(0)\n            expected = (1, self.config.action_horizon, self.config.action_dim)\n            if tuple(noise_tensor.shape) != expected:\n                raise ValueError(\n                    f\"Pi05 noise must have shape {expected}, \"\n                    f\"got {tuple(noise_tensor.shape)}\"\n                )","sourceCodeStart":167,"sourceCodeEnd":203,"githubUrl":"https://github.com/sgl-project/sglang/blob/0132848349585cfe6aae51c4941cbae872505f8a/python/sglang/multimodal_gen/runtime/pipelines_core/stages/model_specific_stages/pi05_preprocess.py#L167-L203","documentation":"The Pi05 v1 stage requires exactly one robot state vector per action request. After converting the state to a float32 tensor (and unsqueezing 1-D inputs to shape [1, D]), it rejects any tensor whose batch dimension is not exactly 1, matching the single-request design of the v1 API.","triggerScenarios":"Passing raw_observation state with shape [N, D] where N > 1 (a batched state matrix), or a nested list like [[s1...],[s2...]] containing multiple state vectors.","commonSituations":"Replaying recorded robot episodes where states are stored as [T, D] time-series arrays and the whole trajectory is passed at once instead of per-timestep; migrating from an ensemble/batched policy.","solutions":["Slice your state array per timestep: state = states[t:t+1] (or states[t] which gets unsqueezed automatically).","Verify state_tensor.ndim is 1 or 2 with shape[0]==1 before calling the stage.","Batch by looping over requests rather than stacking states along dim 0."],"exampleFix":"# before\nstate = episode_states  # shape [T, D]\nstage({\"state\": state, ...})\n\n# after\nfor t in range(episode_states.shape[0]):\n    stage({\"state\": episode_states[t], ...})","handlingStrategy":"validation","validationCode":"import torch\ns = torch.as_tensor(state, dtype=torch.float32)\nif s.ndim == 1:\n    s = s.unsqueeze(0)\nassert s.shape[0] == 1, f\"expected 1 state, got {s.shape[0]}\"","typeGuard":"def is_single_state(state) -> bool:\n    if state is None: return True\n    s = torch.as_tensor(state)\n    return s.ndim <= 2 and (s.ndim < 2 or s.shape[0] == 1)","tryCatchPattern":null,"preventionTips":["Index recorded trajectories per timestep before building the request.","Log state tensor shape right before the call during integration."],"tags":["pi05","vla","state-input","batch-size","torch"],"backgroundTag":"tensor-shape-mismatch","analyzedSha":"0132848349585cfe6aae51c4941cbae872505f8a","analyzedAt":"2026-08-28T05:10:05.995Z","schemaVersion":2},"datasetVersion":"2026-08-28T06:17:29.519Z"}