{"record":{"id":"3eba4ce13c029ae2","repo":"invoke-ai/InvokeAI","slug":"y-min-self-y-min-is-greater-than-y-max-self","errorCode":null,"errorMessage":"y_min ({self.y_min}) is greater than y_max ({self.y_max}).","messagePattern":"y_min \\((.+?)\\) is greater than y_max \\((.+?)\\)\\.","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"invokeai/backend/image_util/segment_anything/shared.py","lineNumber":18,"sourceCode":"from enum import Enum\n\nfrom pydantic import BaseModel, model_validator\nfrom pydantic.fields import Field\n\n\nclass BoundingBox(BaseModel):\n    x_min: int = Field(..., description=\"The minimum x-coordinate of the bounding box (inclusive).\")\n    x_max: int = Field(..., description=\"The maximum x-coordinate of the bounding box (exclusive).\")\n    y_min: int = Field(..., description=\"The minimum y-coordinate of the bounding box (inclusive).\")\n    y_max: int = Field(..., description=\"The maximum y-coordinate of the bounding box (exclusive).\")\n\n    @model_validator(mode=\"after\")\n    def check_coords(self):\n        if self.x_min > self.x_max:\n            raise ValueError(f\"x_min ({self.x_min}) is greater than x_max ({self.x_max}).\")\n        if self.y_min > self.y_max:\n            raise ValueError(f\"y_min ({self.y_min}) is greater than y_max ({self.y_max}).\")\n        return self\n\n    def tuple(self) -> tuple[int, int, int, int]:\n        \"\"\"\n        Returns the bounding box as a tuple suitable for use with PIL's `Image.crop()` method.\n        This method returns a tuple of the form (left, upper, right, lower) == (x_min, y_min, x_max, y_max).\n        \"\"\"\n        return (self.x_min, self.y_min, self.x_max, self.y_max)\n\n\nclass SAMPointLabel(Enum):\n    negative = -1\n    neutral = 0\n    positive = 1\n\n\nclass SAMPoint(BaseModel):\n    x: int = Field(..., description=\"The x-coordinate of the point\")","sourceCodeStart":1,"sourceCodeEnd":36,"githubUrl":"https://github.com/invoke-ai/InvokeAI/blob/0b6a024f2ff6a86bfb953dcdb9cc504ef7397a06/invokeai/backend/image_util/segment_anything/shared.py#L1-L36","documentation":"BoundingBox is a pydantic model whose model_validator `check_coords` enforces that coordinate mins do not exceed maxes. This error means a BoundingBox was constructed with y_min > y_max, i.e. an inverted vertical interval. The library throws it at validation time because an inverted box is meaningless for cropping/segmentation and would break downstream PIL crop and SAM prompt logic.","triggerScenarios":"Calling BoundingBox(y_min=Y, y_max=Y2, ...) with Y2 < Y, e.g. swapping y_min/y_max when converting from a (top, bottom) or (y1, y2) convention, or computing y bounds from data with a wrong sign/ordering.","commonSituations":"Converting coordinates between formats where y order differs (image top-left vs math bottom-left), sorting rectangle corners incorrectly, or hand-writing a crop region where the user typed the upper/lower values in the wrong order.","solutions":["Swap the y_min and y_max values so y_min <= y_max (remember y grows downward in image coordinates: y_min is the top edge).","Sort the y coordinates of your region: y_min, y_max = min(a,b), max(a,b) before constructing BoundingBox.","Check the source of the coordinates (UI selection, crop tuple, model output) for an ordering or sign bug."],"exampleFix":"// before\nBoundingBox(x_min=10, x_max=200, y_min=300, y_max=100)  # inverted y range\n// after\nBoundingBox(x_min=10, x_max=200, y_min=100, y_max=300)","handlingStrategy":"validation","validationCode":"def make_bbox(x_min: int, x_max: int, y_min: int, y_max: int) -> dict:\n    if y_min > y_max:\n        y_min, y_max = y_max, y_min\n    if x_min > x_max:\n        x_min, x_max = x_max, x_min\n    return {\"x_min\": x_min, \"x_max\": x_max, \"y_min\": y_min, \"y_max\": y_max}","typeGuard":"def is_valid_bbox(b: BoundingBox) -> bool:\n    return b.x_min <= b.x_max and b.y_min <= b.y_max","tryCatchPattern":"try:\n    box = BoundingBox(**coords)\nexcept ValueError as e:\n    logger.warning(\"invalid bounding box: %s\", e)\n    box = None  # or auto-correct by swapping mins/maxes","preventionTips":["Normalize corner order (min/max) right where coordinates are captured, before model construction.","Remember image y-axis grows downward; label variables top/bottom rather than min/max when converting from UI selections.","Add a unit test that round-trips a BoundingBox through .tuple() and PIL Image.crop()."],"tags":["validation","pydantic","image","bounding-box"],"backgroundTag":"invalid-coordinate-range","analyzedSha":"0b6a024f2ff6a86bfb953dcdb9cc504ef7397a06","analyzedAt":"2026-08-29T04:46:49.967Z","schemaVersion":2},"datasetVersion":"2026-08-29T07:17:48.351Z"}