BUG #19472: CAST(-32768::SMALLINT AS REAL) fails with "SMALLINT out of range" but -32768 is valid SMALLINT value
The following bug has been logged on the website:
Bug reference: 19472
Logged by: Pisces Mar.
Email address: vectorplanck@gmail.com
PostgreSQL version: 17.6
Operating system: x86_64-windows
Description:
Issue Description:
When casting -32768 to SMALLINT and then to REAL using the :: operator,
PostgreSQL throws an error "smallint out of range", even though -32768 is a
valid value within the SMALLINT range (-32768 to +32767).
Steps to Reproduce:
1. Execute: SELECT CAST(-32768 :: SMALLINT AS REAL);
Result: ERROR: SMALLINT out of range
2. Execute: SELECT CAST((-32768) :: SMALLINT AS REAL);
Result: Successfully returns -32768
3. Execute: SELECT CAST(CAST(-32768 AS SMALLINT) AS REAL);
Result: Successfully returns -32768
Root Cause:
The expression -32768 :: SMALLINT is being parsed as -(32768 :: SMALLINT)
instead of (-32768) :: SMALLINT. Since 32768 exceeds the maximum positive
value for SMALLINT (32767), it causes an out-of-range error.
Expected Behavior:
-32768 should be recognized as a valid SMALLINT value (the minimum value for
smallint is -32768), and the cast to REAL should succeed.
Workaround:
Use parentheses: SELECT CAST((-32768) :: SMALLINT AS REAL);
Or use standard CAST syntax: SELECT CAST(-32768 AS SMALLINT);
Environment:
PostgreSQL Version: 17.6
Operating System: x86_64-windows
On Wed, 2026-05-06 at 09:09 +0000, PG Bug reporting form wrote:
When casting -32768 to SMALLINT and then to REAL using the :: operator,
PostgreSQL throws an error "smallint out of range", even though -32768 is a
valid value within the SMALLINT range (-32768 to +32767).Expected Behavior:
-32768 should be recognized as a valid SMALLINT value (the minimum value for
smallint is -32768), and the cast to REAL should succeed.
This is not a bug, but working as expected.
The documentation at https://www.postgresql.org/docs/current/sql-syntax-lexical.html#SQL-PRECEDENCE
clearly states that the typecast operator :: has higher precedence than
an unary minus.
Yours,
Laurenz Albe
On Wednesday, May 6, 2026, PG Bug reporting form <noreply@postgresql.org>
wrote:
The following bug has been logged on the website:
Bug reference: 19472
Logged by: Pisces Mar.
Email address: vectorplanck@gmail.com
PostgreSQL version: 17.6
Operating system: x86_64-windows
Description:Issue Description:
When casting -32768 to SMALLINT and then to REAL using the :: operator,
PostgreSQL throws an error "smallint out of range", even though -32768 is a
valid value within the SMALLINT range (-32768 to +32767).Workaround:
Use parentheses: SELECT CAST((-32768) :: SMALLINT AS REAL);
Or use standard CAST syntax: SELECT CAST(-32768 AS SMALLINT);
These aren’t really workarounds; this is just how you need to write the
expression given our long-established and not going to change operator
precedence and literal syntax parsing rules.
David J.