invoke-ai/InvokeAI · error · ValueError

y_min ({self.y_min}) is greater than y_max ({self.y_max}).

Error message

y_min ({self.y_min}) is greater than y_max ({self.y_max}).

What it means

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.

Source

Thrown at invokeai/backend/image_util/segment_anything/shared.py:18

from enum import Enum

from pydantic import BaseModel, model_validator
from pydantic.fields import Field


class BoundingBox(BaseModel):
    x_min: int = Field(..., description="The minimum x-coordinate of the bounding box (inclusive).")
    x_max: int = Field(..., description="The maximum x-coordinate of the bounding box (exclusive).")
    y_min: int = Field(..., description="The minimum y-coordinate of the bounding box (inclusive).")
    y_max: int = Field(..., description="The maximum y-coordinate of the bounding box (exclusive).")

    @model_validator(mode="after")
    def check_coords(self):
        if self.x_min > self.x_max:
            raise ValueError(f"x_min ({self.x_min}) is greater than x_max ({self.x_max}).")
        if self.y_min > self.y_max:
            raise ValueError(f"y_min ({self.y_min}) is greater than y_max ({self.y_max}).")
        return self

    def tuple(self) -> tuple[int, int, int, int]:
        """
        Returns the bounding box as a tuple suitable for use with PIL's `Image.crop()` method.
        This method returns a tuple of the form (left, upper, right, lower) == (x_min, y_min, x_max, y_max).
        """
        return (self.x_min, self.y_min, self.x_max, self.y_max)


class SAMPointLabel(Enum):
    negative = -1
    neutral = 0
    positive = 1


class SAMPoint(BaseModel):
    x: int = Field(..., description="The x-coordinate of the point")

View on GitHub (pinned to 0b6a024f2f)

Solutions

  1. 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).
  2. Sort the y coordinates of your region: y_min, y_max = min(a,b), max(a,b) before constructing BoundingBox.
  3. Check the source of the coordinates (UI selection, crop tuple, model output) for an ordering or sign bug.

Example fix

// before
BoundingBox(x_min=10, x_max=200, y_min=300, y_max=100)  # inverted y range
// after
BoundingBox(x_min=10, x_max=200, y_min=100, y_max=300)
Defensive patterns

Strategy: validation

Validate before calling

def make_bbox(x_min: int, x_max: int, y_min: int, y_max: int) -> dict:
    if y_min > y_max:
        y_min, y_max = y_max, y_min
    if x_min > x_max:
        x_min, x_max = x_max, x_min
    return {"x_min": x_min, "x_max": x_max, "y_min": y_min, "y_max": y_max}

Type guard

def is_valid_bbox(b: BoundingBox) -> bool:
    return b.x_min <= b.x_max and b.y_min <= b.y_max

Try / catch

try:
    box = BoundingBox(**coords)
except ValueError as e:
    logger.warning("invalid bounding box: %s", e)
    box = None  # or auto-correct by swapping mins/maxes

Prevention

When it happens

Trigger: 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.

Common situations: 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.

Related errors


AI-assisted analysis of invoke-ai/InvokeAI@0b6a024f2f (2026-08-29). Data as JSON: /api/errors/3eba4ce13c029ae2. Report an issue: GitHub.