{"record":{"id":"8b9e268572b5d3b2","repo":"sgl-project/sglang","slug":"minimax-h3-initial-audio-rows-must-be-a-rank-2-ten","errorCode":null,"errorMessage":"MiniMax H3 initial_audio_rows must be a rank-2 tensor","messagePattern":"MiniMax H3 initial_audio_rows must be a rank-2 tensor","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"python/sglang/multimodal_gen/runtime/pipelines_core/stages/model_specific_stages/minimax_h3/stages/latent_preparation.py","lineNumber":55,"sourceCode":"    ) -> list[Req]:\n        \"\"\"Preserve H3's independent per-modality RNG streams per request.\"\"\"\n        return [self(batch, server_args) for batch in batches]\n\n    @staticmethod\n    def _publish_native_latent_state(batch: Req) -> None:\n        from sglang.multimodal_gen.runtime.pipelines_core.stages.model_specific_stages.minimax_h3.constants import (\n            MINIMAX_H3_DENOISE_STATE_EXTRA_KEY,\n        )\n\n        state = batch.extra.get(MINIMAX_H3_DENOISE_STATE_EXTRA_KEY)\n        if not isinstance(state, dict):\n            raise ValueError(\"MiniMax H3 denoise state must be a mapping\")\n        video_rows = state.get(\"initial_video_rows\")\n        audio_rows = state.get(\"initial_audio_rows\")\n        if not isinstance(video_rows, torch.Tensor) or video_rows.ndim != 2:\n            raise ValueError(\"MiniMax H3 initial_video_rows must be a rank-2 tensor\")\n        if not isinstance(audio_rows, torch.Tensor) or audio_rows.ndim != 2:\n            raise ValueError(\"MiniMax H3 initial_audio_rows must be a rank-2 tensor\")\n\n        latent_t = int(state[\"latent_t\"])\n        latent_h = int(state[\"latent_h\"])\n        latent_w = int(state[\"latent_w\"])\n        audio_t = int(state[\"audio_t\"])\n        batch.latents = video_rows\n        batch.audio_latents = audio_rows\n        batch.raw_latent_shape = (1, 24, latent_t, latent_h, latent_w)\n        batch.raw_audio_latent_shape = (2, 32, audio_t)\n\n    def _prepare_denoise_state_from_plan(self, batch: Req, plan) -> None:\n        \"\"\"Direct initial-noise materialization (t2va recipe):\n        torch.Generator().manual_seed(seed); video rows drawn first,\n        then audio rows, CPU fp32. Every task consumes the final latent grid\n        frozen by the pre-queue shape resolver.\"\"\"\n        from sglang.multimodal_gen.runtime.pipelines_core.stages.model_specific_stages.minimax_h3.constants import (\n            MINIMAX_H3_DENOISE_STATE_EXTRA_KEY,\n        )","sourceCodeStart":37,"sourceCodeEnd":73,"githubUrl":"https://github.com/sgl-project/sglang/blob/0132848349585cfe6aae51c4941cbae872505f8a/python/sglang/multimodal_gen/runtime/pipelines_core/stages/model_specific_stages/minimax_h3/stages/latent_preparation.py#L37-L73","documentation":"Twin of the video rows check: the stage requires state['initial_audio_rows'] to be a torch.Tensor with exactly 2 dimensions (expected shape [audio_rows_n, 32]). The error fires when the audio noise entry is missing, not a tensor, or rank != 2.","triggerScenarios":"_publish_native_latent_state runs with initial_audio_rows set to None, a non-tensor, or a wrongly-ranked tensor (e.g. [1, N, 32]) in batch.extra[MINIMAX_H3_DENOISE_STATE_EXTRA_KEY].","commonSituations":"Injecting or deserializing denoise state where audio noise was transposed, stacked, or converted; omitting the audio branch for audio-capable requests.","solutions":["Provide initial_audio_rows as a rank-2 tensor of shape [audio_rows_n, 32]","Fix rank by squeezing/reshaping or converting via torch.as_tensor before publishing","Let the stage build the state from the plan (video_latent_t/audio_latent_t) rather than manual injection"],"exampleFix":"// before\nstate[\"initial_audio_rows\"] = np_audio  # numpy, not tensor\n// after\nstate[\"initial_audio_rows\"] = torch.as_tensor(np_audio, dtype=torch.float32)  # [N, 32]","handlingStrategy":"type-guard","validationCode":"rows = state.get(\"initial_audio_rows\")\nassert isinstance(rows, torch.Tensor) and rows.ndim == 2 and rows.shape[1] == 32, rows.shape if isinstance(rows, torch.Tensor) else type(rows)","typeGuard":"def is_valid_audio_rows(x) -> bool:\n    return isinstance(x, torch.Tensor) and x.ndim == 2 and x.shape[-1] == 32","tryCatchPattern":null,"preventionTips":["Convert numpy audio noise via torch.as_tensor before publishing","Keep audio noise unbatched: [rows, 32], never [1, rows, 32]"],"tags":["minimax-h3","tensor-shape","batch-state"],"backgroundTag":"tensor-rank-validation","analyzedSha":"0132848349585cfe6aae51c4941cbae872505f8a","analyzedAt":"2026-08-28T05:10:05.995Z","schemaVersion":2},"datasetVersion":"2026-08-28T06:17:29.519Z"}