{"record":{"id":"1afdb5e8177ab403","repo":"sgl-project/sglang","slug":"all-frames-in-a-batch-must-have-the-same-resolutio","errorCode":null,"errorMessage":"All frames in a batch must have the same resolution","messagePattern":"All frames in a batch must have the same resolution","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"python/sglang/multimodal_gen/runtime/postprocess/realesrgan_upscaler.py","lineNumber":456,"sourceCode":"            target_h = int(h * outscale)\n            target_w = int(w * outscale)\n            out = F.interpolate(\n                out, size=(target_h, target_w), mode=\"bicubic\", align_corners=False\n            )\n\n        out_np = out.squeeze(0).permute(1, 2, 0).clamp(0.0, 1.0).cpu().numpy()\n        return (out_np * 255.0).astype(np.uint8)\n\n    def upscale_batch(\n        self, frames: list[np.ndarray], outscale: float | None = None\n    ) -> list[np.ndarray]:\n        \"\"\"Upscale same-resolution HWC uint8 frames in one batched forward pass.\"\"\"\n        if not frames:\n            return []\n\n        h, w = frames[0].shape[:2]\n        if any(frame.shape[:2] != (h, w) for frame in frames):\n            raise ValueError(\"All frames in a batch must have the same resolution\")\n\n        total_start_time = time.perf_counter()\n\n        start_time = time.perf_counter()\n        imgs = np.stack(frames, axis=0)\n        stack_duration_s = time.perf_counter() - start_time\n\n        start_time = time.perf_counter()\n        h2d_timer = self._start_cuda_timer()\n        imgs_t = self._copy_input_to_device(imgs)\n        self._stop_cuda_timer(h2d_timer)\n        h2d_wall_duration_s = time.perf_counter() - start_time\n\n        start_time = time.perf_counter()\n        input_preprocess_timer = self._start_cuda_timer()\n        imgs_t = self._preprocess_input_tensor(imgs_t)\n        self._stop_cuda_timer(input_preprocess_timer)\n        input_preprocess_wall_duration_s = time.perf_counter() - start_time","sourceCodeStart":438,"sourceCodeEnd":474,"githubUrl":"https://github.com/sgl-project/sglang/blob/0132848349585cfe6aae51c4941cbae872505f8a/python/sglang/multimodal_gen/runtime/postprocess/realesrgan_upscaler.py#L438-L474","documentation":"Raised by RealESRGANUpscaler.upscale_batch when frames passed in one batch do not all share the same (H, W), since the implementation stacks them into a single numpy array for one batched forward pass.","triggerScenarios":"Calling upscale_batch (or upscale_batched which groups frames) with a list containing frames of differing resolutions, e.g. mixing 1080p and 720p frames or portrait/landscape variants.","commonSituations":"Feeding raw video frames without normalization; mixing images from mixed sources; upstream crop/reszie step skipped.","solutions":["Resize/pad all frames to a common resolution before batching","Group frames by resolution and call upscale_batch once per group"],"exampleFix":"# before\nouts = upscaler.upscale_batch([f1080, f720])\n# after\nfrom torchvision.transforms import functional as F\nframes = [cv2.resize(f, (W, H)) for f in frames]\nouts = upscaler.upscale_batch(frames)","handlingStrategy":"validation","validationCode":"from itertools import groupby\nframes.sort(key=lambda f: f.shape[:2])  # or group explicitly\nshapes = {f.shape[:2] for f in frames}\nassert len(shapes) <= 1 or batched_per_group, \"mixed resolutions\"","typeGuard":"def frames_uniform(frames: list) -> bool:\n    return all(f.shape[:2] == frames[0].shape[:2] for f in frames)","tryCatchPattern":null,"preventionTips":["Normalize frame resolution upstream in the video pipeline","Group frames by resolution before calling upscale_batch"],"tags":["realesrgan","batch","resolution","postprocess"],"backgroundTag":"batch-shape-mismatch","analyzedSha":"0132848349585cfe6aae51c4941cbae872505f8a","analyzedAt":"2026-08-28T05:10:05.995Z","schemaVersion":2},"datasetVersion":"2026-08-28T06:17:29.519Z"}