{"record":{"id":"5d86bd1118472528","repo":"invoke-ai/InvokeAI","slug":"x-min-self-x-min-is-greater-than-x-max-self","errorCode":null,"errorMessage":"x_min ({self.x_min}) is greater than x_max ({self.x_max}).","messagePattern":"x_min \\((.+?)\\) is greater than x_max \\((.+?)\\)\\.","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"invokeai/backend/image_util/segment_anything/shared.py","lineNumber":16,"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","sourceCodeStart":1,"sourceCodeEnd":34,"githubUrl":"https://github.com/invoke-ai/InvokeAI/blob/0b6a024f2ff6a86bfb953dcdb9cc504ef7397a06/invokeai/backend/image_util/segment_anything/shared.py#L1-L34","documentation":"The segment-anything bounding-box pydantic model validates itself with a @model_validator(mode='after'): if x_min > x_max (or y_min > y_max) the box is inverted/empty and ValueError('x_min (...) is greater than x_max (...).') is raised during construction. The library enforces the inclusive-min / exclusive-max box convention so downstream cropping produces a non-empty region.","triggerScenarios":"Constructing the box model (directly or via an API taking box coordinates) with x_min greater than x_max — e.g. passing corners in the wrong order (right, left), boxes computed as (x + w, x) inverted, or negative/NaN-derived widths flowing into the fields.","commonSituations":"Swapping the two x (or y) coordinates when converting from (x, y, w, h) or corner-pair formats; results from detection models returned with unordered corners; coordinate-space confusion (normalized 0-1 vs pixel) producing out-of-order values; negative widths from sign errors.","solutions":["Normalize the coordinates before constructing: x_min = min(x1, x2), x_max = max(x1, x2) (same for y).","If the source box is (x, y, w, h), pass (x, y, x + w, y + h) and ensure w, h >= 0.","Clamp or reject upstream boxes with negative width/height before they reach the model.","Catch pydantic ValidationError at the API boundary to report which coordinates were inverted."],"exampleFix":"// before\nBox(x_min=x2, y_min=y1, x_max=x1, y_max=y2)  # ValueError if x1 < x2\n// after\nBox(x_min=min(x1, x2), y_min=min(y1, y2), x_max=max(x1, x2), y_max=max(y1, y2))","handlingStrategy":"validation","validationCode":"def normalize_box(x1, y1, x2, y2):\n    assert x1 <= x2 and y1 <= y2, f'inverted box: ({x1},{y1},{x2},{y2})'\n    return x1, y1, x2, y2","typeGuard":"def is_valid_box(box) -> bool:\n    return box.x_min <= box.x_max and box.y_min <= box.y_max","tryCatchPattern":"from pydantic import ValidationError\ntry:\n    box = BoundingBox(x_min=x1, y_min=y1, x_max=x2, y_max=y2)\nexcept ValidationError as e:\n    logger.error('Invalid box coords (%s, %s, %s, %s): %s', x1, y1, x2, y2, e)\n    box = BoundingBox(x_min=min(x1, x2), y_min=min(y1, y2), x_max=max(x1, x2), y_max=max(y1, y2))","preventionTips":["Always normalize corners with min/max at the point where boxes are created.","Convert (x, y, w, h) to corners explicitly and reject negative w/h upstream.","Be explicit about normalized vs pixel coordinate spaces in one conversion utility.","Keep the inclusive-min / exclusive-max convention documented at API boundaries."],"tags":["python","pydantic","validation","bounding-box"],"backgroundTag":"bbox-min-greater-than-max","analyzedSha":"0b6a024f2ff6a86bfb953dcdb9cc504ef7397a06","analyzedAt":"2026-08-29T04:46:49.967Z","schemaVersion":2},"datasetVersion":"2026-08-29T07:17:48.351Z"}