django/django · error · GDALException

Envelope minimum X > maximum X.

Error message

Envelope minimum X > maximum X.

What it means

Raised by Envelope.__init__ (django/contrib/gis/gdal/envelope.py:69) as a GDALException after the envelope fields are populated, when min_x > max_x. A bounding box is meaningless if its left edge is to the right of its right edge, so the constructor refuses to produce an invalid envelope.

Source

Thrown at django/contrib/gis/gdal/envelope.py:69

                # A tuple was passed in.
                if len(args[0]) != 4:
                    raise GDALException(
                        "Incorrect number of tuple elements (%d)." % len(args[0])
                    )
                else:
                    self._from_sequence(args[0])
            else:
                raise TypeError("Incorrect type of argument: %s" % type(args[0]))
        elif len(args) == 4:
            # Individual parameters passed in.
            #  Thanks to ww for the help
            self._from_sequence([float(a) for a in args])
        else:
            raise GDALException("Incorrect number (%d) of arguments." % len(args))

        # Checking the x,y coordinates
        if self.min_x > self.max_x:
            raise GDALException("Envelope minimum X > maximum X.")
        if self.min_y > self.max_y:
            raise GDALException("Envelope minimum Y > maximum Y.")

    def __eq__(self, other):
        """
        Return True if the envelopes are equivalent; can compare against
        other Envelopes and 4-tuples.
        """
        if isinstance(other, Envelope):
            return (
                (self.min_x == other.min_x)
                and (self.min_y == other.min_y)
                and (self.max_x == other.max_x)
                and (self.max_y == other.max_y)
            )
        elif isinstance(other, tuple) and len(other) == 4:
            return (
                (self.min_x == other[0])

View on GitHub (pinned to ae25a40be0)

Solutions

  1. Reorder coordinates so min_x <= max_x: Envelope((min(a,c), b, max(a,c), d)).
  2. Normalize the source extent with min/max before construction.
  3. For antimeridian geometries, split or shift longitudes before computing the envelope.
  4. Check the source documentation for its extent axis order.

Example fix

// before
env = Envelope((xmax, ymin, xmin, ymax))   # minx > maxx -> error
// after
env = Envelope((xmin, ymin, xmax, ymax))   # canonical (min_x, min_y, max_x, max_y)
Defensive patterns

Strategy: validation

Validate before calling

minx, miny, maxx, maxy = extent
if minx > maxx:
    minx, maxx = min(minx, maxx), max(minx, maxx)
env = Envelope((minx, miny, maxx, maxy))

Type guard

def x_axis_valid(extent) -> bool:
    return extent[0] <= extent[2]

Try / catch

from django.contrib.gis.gdal.error import GDALException
try:
    env = Envelope(extent)
except GDALException:
    a, b, c, d = extent
    env = Envelope((min(a, c), b, max(a, c), d))  # normalize X

Prevention

When it happens

Trigger: Envelope((10.0, 0.0, 5.0, 5.0)) where minx=10 > maxx=5. Swapped coordinate order from a source that emits (maxx, miny, minx, maxy). Off-by-one or sign error in computed extents. Negative-longitude crossing handled incorrectly.

Common situations: Datasets that report extent as (xmax, ymin, xmin, ymax) rather than (xmin, ymin, xmax, ymax). UI bounding boxes where the user drags right-to-left. Antimeridian-crossing geometries whose raw bbox wraps.

Related errors


AI-assisted analysis of django/django@ae25a40be0 (2026-08-06). Data as JSON: /api/errors/6c151de41649ffdb. Report an issue: GitHub.