{"record":{"id":"76073fa414ca5bad","repo":"sgl-project/sglang","slug":"image-aspect-ratio-must-be-smaller-than-200","errorCode":null,"errorMessage":"Image aspect ratio must be smaller than 200","messagePattern":"Image aspect ratio must be smaller than 200","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"python/sglang/srt/models/dots3_common/dots_omni_towers.py","lineNumber":132,"sourceCode":"    def _resized_size(\n        self,\n        width: int,\n        height: int,\n        min_pixels: int,\n        max_pixels: int,\n        target_height=None,\n        target_width=None,\n    ):\n        height = target_height or height\n        width = target_width or width\n        factor = self.patch_size * self.merge_size\n        if min(height, width) < factor // 4:\n            raise ValueError(\n                f\"Image height/width must be at least {factor // 4}, \"\n                f\"got {height}x{width}\"\n            )\n        if max(height, width) / min(height, width) > 200:\n            raise ValueError(\"Image aspect ratio must be smaller than 200\")\n        resized_h = max(factor, self._round_by_factor(height, factor))\n        resized_w = max(factor, self._round_by_factor(width, factor))\n        if resized_h * resized_w > max_pixels:\n            beta = math.sqrt(height * width / max_pixels)\n            resized_h = max(factor, self._floor_by_factor(height / beta, factor))\n            resized_w = max(factor, self._floor_by_factor(width / beta, factor))\n        elif resized_h * resized_w < min_pixels:\n            beta = math.sqrt(min_pixels / (height * width))\n            resized_h = self._ceil_by_factor(height * beta, factor)\n            resized_w = self._ceil_by_factor(width * beta, factor)\n            if resized_h * resized_w > max_pixels:\n                beta = math.sqrt(resized_h * resized_w / max_pixels)\n                resized_h = max(factor, self._floor_by_factor(resized_h / beta, factor))\n                resized_w = max(factor, self._floor_by_factor(resized_w / beta, factor))\n        return resized_h, resized_w\n\n    def _process_image(self, image, detail=\"auto\"):\n        if not isinstance(image, Image.Image):","sourceCodeStart":114,"sourceCodeEnd":150,"githubUrl":"https://github.com/sgl-project/sglang/blob/0132848349585cfe6aae51c4941cbae872505f8a/python/sglang/srt/models/dots3_common/dots_omni_towers.py#L114-L150","documentation":"Raised by the Dots3 vision tower's image preprocessing when the input image's aspect ratio (max dimension / min dimension) exceeds 200. The processor enforces this bound because the smart-resize logic rounds each side up to a factor multiple, and an extremely elongated image would explode into an enormous number of vision tokens / patches. It is a hard validation of user-supplied image geometry.","triggerScenarios":"Calling process_images (which calls _process_image -> _resized_size) with an image whose max(height,width)/min(height,width) > 200, e.g. a 20000x50 pixel strip. Any min side >= factor//4 check passing earlier does not protect against this; only the ratio matters.","commonSituations":"Feeding scanned banners, long receipts, thin lines, or corrupted/mis-decoded images into a Dots3 multimodal request; images produced by cropping pipelines that keep one dimension tiny; accidentally swapping coordinates.","solutions":["Pre-crop or resize the image so its aspect ratio is below 200 before sending it to the model","Verify the image is not corrupted or zero-width/height (decode it with PIL and check image.size)","If long documents are the goal, split the image into tiles/pages each within the ratio limit","Add a client-side guard: compute max(h,w)/min(h,w) and reject/downscale before calling process_images"],"exampleFix":"# before\nimage = Image.open('banner_20000x50.png')\nprocessor.process_images([image])\n\n# after\nh, w = image.size\nif max(h, w) / min(h, w) > 200:\n    raise ValueError('crop or resize: aspect ratio too large')\nprocessor.process_images([image])","handlingStrategy":"validation","validationCode":"from PIL import Image\n\ndef check_aspect(img: Image.Image, limit: float = 200.0) -> bool:\n    w, h = img.size\n    return max(w, h) / min(w, h) <= limit","typeGuard":null,"tryCatchPattern":"try:\n    processor.process_images([img])\nexcept ValueError as e:\n    if 'aspect ratio' in str(e):\n        img = crop_or_tile_to_ratio(img)\n    else:\n        raise","preventionTips":["Validate image.size on ingest","Tile very elongated images before inference","Reject images with min dimension < 4px"],"tags":["dots3","vision","image-preprocessing","aspect-ratio","multimodal"],"backgroundTag":"image-dimension-validation","analyzedSha":"0132848349585cfe6aae51c4941cbae872505f8a","analyzedAt":"2026-08-28T05:10:05.995Z","schemaVersion":2},"datasetVersion":"2026-08-28T06:17:29.519Z"}