{"record":{"id":"0f858d7871e0f1ac","repo":"roboflow/supervision","slug":"new-image-shape-must-contain-positive-dimensions","errorCode":null,"errorMessage":"new_image_shape must contain positive dimensions","messagePattern":"new_image_shape must contain positive dimensions","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"src/supervision/detection/compact_mask.py","lineNumber":1504,"sourceCode":"            Crops are clipped to stay inside ``new_image_shape``; masks fully\n            outside are represented as ``1x1`` all-False crops.\n\n        Examples:\n            ```pycon\n            >>> import numpy as np\n            >>> from supervision.detection.compact_mask import CompactMask\n            >>> masks = np.zeros((1, 20, 20), dtype=bool)\n            >>> xyxy = np.array([[5, 5, 15, 15]], dtype=np.float32)\n            >>> cm = CompactMask.from_dense(masks, xyxy, image_shape=(20, 20))\n            >>> cm2 = cm.with_offset(100, 200, new_image_shape=(400, 400))\n            >>> cm2.offsets[0].tolist()\n            [105, 205]\n\n            ```\n        \"\"\"\n        new_h, new_w = new_image_shape\n        if new_h <= 0 or new_w <= 0:\n            raise ValueError(\"new_image_shape must contain positive dimensions\")\n\n        num_masks = len(self)\n        if num_masks == 0:\n            return CompactMask(\n                [],\n                np.empty((0, 2), dtype=np.int32),\n                np.empty((0, 2), dtype=np.int32),\n                new_image_shape,\n            )\n\n        # Vectorised bounds check: compute every new [x1,y1,x2,y2] at once.\n        # For the common case (InferenceSlicer tiles that fit fully inside the\n        # new canvas) this catches the \"no clipping needed\" path in O(N) numpy\n        # without touching any RLE data.\n        new_offsets: npt.NDArray[np.int32] = self._offsets + np.array(\n            [dx, dy], dtype=np.int32\n        )\n        x1s = new_offsets[:, 0]","sourceCodeStart":1486,"sourceCodeEnd":1522,"githubUrl":"https://github.com/roboflow/supervision/blob/7f254d9784d4c37e0f03cd89ddee164c8db099c0/src/supervision/detection/compact_mask.py#L1486-L1522","documentation":"Raised by CompactMask.with_offset when new_image_shape contains a zero or negative height or width. The method re-embeds each mask crop at a new offset on a canvas of the given size, so the canvas must be positively sized before bounds checks run.","triggerScenarios":"Calling cm.with_offset(dx, dy, new_image_shape=(0, 400)) or with negative dims; computing new_image_shape from an arithmetic expression (old_shape - margins) that can reach 0 or below for edge-case tiles.","commonSituations":"Stitching InferenceSlicer tiles back together with a shape computed as min/max of tile coordinates that degenerates; passing (w, h) where one entry was 0; off-by-one making a dimension negative near image borders.","solutions":["Compute the destination canvas from the original image: new_image_shape = img.shape[:2], not from tile arithmetic.","Clamp/validate computed shapes: assert h > 0 and w > 0 before calling with_offset.","Skip fully out-of-canvas tiles rather than constructing a zero-size canvas for them."],"exampleFix":"# before\ncm2 = cm.with_offset(x, y, new_image_shape=(max(0, W - x - w), H))\n\n# after\ncm2 = cm.with_offset(x, y, new_image_shape=img.shape[:2])","handlingStrategy":"validation","validationCode":"new_h, new_w = new_image_shape\nassert new_h > 0 and new_w > 0, f\"bad new_image_shape {(new_h, new_w)}\"\ncm2 = cm.with_offset(dx, dy, new_image_shape=(new_h, new_w))","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Use the destination image's .shape[:2] as new_image_shape, not arithmetic on tile coordinates.","Skip tiles that fall entirely outside the destination canvas.","Unit-test stitching code with tiles at image borders where degenerate shapes arise."],"tags":["compact-mask","offset","image-shape","slicing","validation"],"backgroundTag":null,"analyzedSha":"7f254d9784d4c37e0f03cd89ddee164c8db099c0","analyzedAt":"2026-08-15T05:13:01.950Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}