{"record":{"id":"02bcd076690fe2c9","repo":"sgl-project/sglang","slug":"minimax-h3-text-payload-positive-text-len-must-mat","errorCode":null,"errorMessage":"MiniMax H3 text payload positive.text_len must match the hidden-state sequence dimension","messagePattern":"MiniMax H3 text payload positive\\.text_len must match the hidden-state sequence dimension","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"python/sglang/multimodal_gen/runtime/pipelines_core/stages/model_specific_stages/minimax_h3/stages/text_encoding.py","lineNumber":231,"sourceCode":"        H3 keeps token tags and presentation metadata in ``Req.extra``, but\n        the shared TextEncodingStage contract still owns ``prompt_embeds``.\n        Publishing the same tensor there preserves native verification,\n        grouped-request deduplication, and downstream memory accounting\n        without duplicating the embedding storage.\n        \"\"\"\n        payload = batch.extra.get(MINIMAX_H3_TEXT_EMBEDDINGS_EXTRA_KEY)\n        positive = payload.get(\"positive\") if isinstance(payload, dict) else None\n        hidden_states = (\n            positive.get(\"hidden_states\") if isinstance(positive, dict) else None\n        )\n        text_len = positive.get(\"text_len\") if isinstance(positive, dict) else None\n        if not isinstance(hidden_states, torch.Tensor) or hidden_states.ndim < 2:\n            raise ValueError(\n                \"MiniMax H3 text payload must contain positive.hidden_states \"\n                \"with at least two dimensions\"\n            )\n        if not isinstance(text_len, int) or text_len != int(hidden_states.shape[0]):\n            raise ValueError(\n                \"MiniMax H3 text payload positive.text_len must match the \"\n                \"hidden-state sequence dimension\"\n            )\n        batch.prompt_embeds = [hidden_states]\n        batch.prompt_seq_lens = [[text_len]]\n\n    def _encode_from_plan(\n        self,\n        batch: Req,\n        plan,\n        *,\n        include_video_token_mask: bool = False,\n    ) -> None:\n        \"\"\"Encode the positive Qwen3VL presentation into layer-50 states.\n\n        MiniMax H3 only supports the CFG-distilled model path, so every task\n        emits exactly one positive embedding payload. ComponentManager owns\n        residency/offload, while every folded-TP rank enters the encoder","sourceCodeStart":213,"sourceCodeEnd":249,"githubUrl":"https://github.com/sgl-project/sglang/blob/0132848349585cfe6aae51c4941cbae872505f8a/python/sglang/multimodal_gen/runtime/pipelines_core/stages/model_specific_stages/minimax_h3/stages/text_encoding.py#L213-L249","documentation":"The payload's positive.text_len must be an int equal to hidden_states.shape[0] (the sequence dimension). This check keeps prompt_seq_lens consistent with the embeddings actually published to batch.prompt_embeds; any mismatch means the payload is internally inconsistent.","triggerScenarios":"_publish_native_text_conditioning finds text_len missing (None), a non-int (e.g. tensor or float), or an int different from hidden_states.shape[0] — e.g. embeddings truncated/padded after text_len was computed.","commonSituations":"Post-processing embeddings (slicing, pooling, padding) without updating text_len; encoders returning text_len as a 0-d tensor instead of int; chunked encodes appending tokens after length was recorded.","solutions":["Recompute text_len from the final tensor: int(hidden_states.shape[0]) and set it in the payload","Convert tensor/float text_len values to int before publishing","Avoid mutating hidden_states after the encoder computed text_len"],"exampleFix":"// before\npayload[\"positive\"][\"text_len\"] = old_len  # before truncation\n// after\nhs = payload[\"positive\"][\"hidden_states\"]\npayload[\"positive\"][\"text_len\"] = int(hs.shape[0])","handlingStrategy":"validation","validationCode":"hs = payload[\"positive\"][\"hidden_states\"]\npayload[\"positive\"][\"text_len\"] = int(hs.shape[0])  # keep consistent before publish","typeGuard":"def text_len_matches(payload) -> bool:\n    pos = payload.get(\"positive\", {})\n    tl, hs = pos.get(\"text_len\"), pos.get(\"hidden_states\")\n    return isinstance(tl, int) and isinstance(hs, torch.Tensor) and tl == hs.shape[0]","tryCatchPattern":null,"preventionTips":["Recompute text_len after any slicing/padding of embeddings","Store text_len as a Python int, not a tensor"],"tags":["minimax-h3","text-encoding","length-mismatch"],"backgroundTag":"length-mismatch-validation","analyzedSha":"0132848349585cfe6aae51c4941cbae872505f8a","analyzedAt":"2026-08-28T05:10:05.995Z","schemaVersion":2},"datasetVersion":"2026-08-28T06:17:29.519Z"}