{"record":{"id":"389292a71a1653f0","repo":"sgl-project/sglang","slug":"grid-dim-mm-grid-attrs-modality-not-found-in","errorCode":null,"errorMessage":"Grid dim ({_mm_grid_attrs[modality]}) not found in {mm_inputs}","messagePattern":"Grid dim \\((.+?)\\) not found in (.+?)","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"python/sglang/srt/disaggregation/encoder/preprocessor.py","lineNumber":659,"sourceCode":"            return (input_length - 2) // 2 + 1\n\n    def _get_mm_grid_dim(self, mm_inputs: dict, modality: Modality):\n        # Kimi K2.5/K3 vision processors only emit `grid_thws`; prefer it over generic keys\n        # so we never pick a mis-typed or stale `image_grid_hws` field from kwargs.\n        attrs = _mm_grid_attrs[modality]\n        model_type = (self.model_type or \"\").lower()\n        if modality == Modality.IMAGE:\n            # Kimi K2.5/K3 emit grid_thws, while Kimi-VL emits image_grid_hws.\n            # Other model types keep the generic attr order above.\n            if model_type in (\"kimi_k25\", \"kimi_k3\"):\n                attrs = (\"grid_thws\", \"image_grid_thw\", \"image_grid_hws\")\n            elif model_type == \"kimi_vl\":\n                attrs = (\"image_grid_hws\", \"image_grid_thw\", \"grid_thws\")\n\n        for attr in attrs:\n            if attr in mm_inputs and mm_inputs[attr] is not None:\n                return _convert(mm_inputs[attr])\n        raise ValueError(\n            f\"Grid dim ({_mm_grid_attrs[modality]}) not found in {mm_inputs}\"\n        )\n\n    def get_num_patches(\n        self, grid: Union[torch.Tensor, List[int]], modality: Modality\n    ) -> int:\n        \"\"\"Calculate number of raw patches (before merge/sampling). Used for pixel_values slicing.\"\"\"\n        if modality == Modality.AUDIO:\n            return int(grid.item())\n        if self.model_type == \"kimi_vl\" and modality == Modality.IMAGE:\n            h, w = self._kimi_hw_from_patch_grid(grid)\n            return h * w\n        return int(grid[0] * grid[1] * grid[2])\n\n    @staticmethod\n    def _kimi_hw_from_patch_grid(\n        grid: Union[torch.Tensor, np.ndarray, List[int], Tuple[int, ...]],\n    ) -> Tuple[int, int]:","sourceCodeStart":641,"sourceCodeEnd":677,"githubUrl":"https://github.com/sgl-project/sglang/blob/0132848349585cfe6aae51c4941cbae872505f8a/python/sglang/srt/disaggregation/encoder/preprocessor.py#L641-L677","documentation":"Thrown by the multimodal preprocessor when it cannot find any of the expected grid-shape keys (e.g. image_grid_thw, grid_thws, image_grid_hws, video_grid_thw) in the mm_inputs dict for the given modality. The grid metadata is required to compute patch counts and token counts for slicing pixel_values. Model-specific key preference applies (kimi_k25/k3 prefer grid_thws, kimi_vl prefers image_grid_hws), but if none of the candidate keys is present and non-None the lookup fails.","triggerScenarios":"Calling process_mm_items (or the encoder pipeline that drives it) with mm_inputs that lack the processor-emitted grid tensor, e.g. passing only pixel_values without image_grid_thw/grid_thws; or a video/audio item where the corresponding grid key was dropped, renamed by a newer transformers version, or serialized to None during disaggregated handoff.","commonSituations":"Upgrading transformers so the vision processor emits a differently-named grid key; hand-crafting mm_inputs dicts in tests or custom clients; deserializing grid metadata that was lost/None'd over the wire; wrong modality key set for the model type.","solutions":["Inspect the failing mm_inputs dict (the message prints it) and confirm which grid key your processor actually emits.","Ensure the output of the HF vision processor (image_grid_thw / grid_thws / video_grid_thw etc.) is passed through unmodified into mm_inputs.","If a custom preprocessor drops keys, add the missing key back or map the new name to the one expected for your model_type.","Check that the value is not None — a None value is treated as missing."],"exampleFix":"// before\nmm_inputs = {\"pixel_values\": pv}  # grid key lost\n// after\nmm_inputs = {\"pixel_values\": pv, \"image_grid_thw\": proc_out[\"image_grid_thw\"]}","handlingStrategy":"validation","validationCode":"from sglang.srt.disaggregation.encoder.preprocessor import _mm_grid_attrs\n\ndef has_grid_dim(mm_inputs: dict, modality) -> bool:\n    return any(\n        k in mm_inputs and mm_inputs[k] is not None\n        for k in _mm_grid_attrs[modality]\n    )","typeGuard":"def has_valid_grid(mm_inputs: dict) -> bool:\n    return isinstance(mm_inputs, dict) and any(\n        isinstance(v, (list, tuple)) and len(v) and all(v)\n        for k, v in mm_inputs.items()\n        if \"grid\" in k or k.endswith(\"_thw\") or k.endswith(\"_hws\")\n    )","tryCatchPattern":"try:\n    grid = prep._get_mm_grid_dim(mm_inputs, modality)\nexcept ValueError as e:\n    raise HTTPException(400, f\"multimodal input missing grid metadata: {e}\") from e","preventionTips":["Always forward the HF vision processor output dict verbatim into mm_inputs instead of cherry-picking keys.","Pin the transformers version so grid key names stay stable.","Assert grid keys are present and non-None in tests for every supported modality."],"tags":["multimodal","preprocessor","grid-metadata","kimi","validation"],"backgroundTag":"missing-required-field","analyzedSha":"0132848349585cfe6aae51c4941cbae872505f8a","analyzedAt":"2026-08-28T05:10:05.995Z","schemaVersion":2},"datasetVersion":"2026-08-28T06:17:29.519Z"}