range lower bound must be less than or equal to range upper bound
SQLSTATE 22000 condition data_exception class 22 — Data Exception severity ERROR
Reproduced & verified on PostgreSQL 14.23, 15.18, 16.14, 17.10 and 18.4 — identical message on every version.
Last reviewed 30 May 2025 · Reproduced live with the SQL on this page.
Symptoms
A range value was constructed with a lower bound greater than its upper bound. PostgreSQL raises SQLSTATE 22000 (data_exception).
- The lower bound exceeds the upper bound.
- Ranges require lower ≤ upper.
- Common with reversed arguments to a range constructor.
What the server log shows
ERROR: range lower bound must be less than or equal to range upper bound
Why PostgreSQL raises this — what the manual says
As Section 8.17 Range Types explains:
A range’s lower bound must not be greater than its upper bound; supplying a lower value that exceeds the upper value is invalid (an empty range is written as the literal ’empty’, not by inverting the bounds).
A non-empty range requires lower ≤ upper. Supplying a lower bound greater than the upper makes no valid interval, so PostgreSQL reports 22000.
Common causes
- Reversed arguments to a range constructor (e.g.
int4range(10, 1)). - Computed bounds that ended up out of order.
- Off-by-one logic producing an inverted interval.
How to fix it
- Pass bounds in order:
int4range(1, 10). - Normalize/sort the bounds before constructing the range.
- Use an empty range form when you intend no values.
Related & next steps
Reference: PostgreSQL 18 Section 8.17 “Range Types”.