Incident brief
Numeric value out of range
A value didn't fit in the numeric type's allowed range. PostgreSQL rejects it instead of wrapping it around or silently rounding it.
What lands in your log
ERROR: smallint out of range
In 10 seconds
- What triggers it
- Create a table with a smallint column.
- Fix
- Use a wider integer type (integer or bigint) if values can legitimately exceed smallint's range.
- Proof
- Reproduced on PostgreSQL 16.14 → Inserting 40000 into a smallint column (documented range -32768 to +32767) was rejected with SQLSTATE 22003. No row was stored.
Fix
What to do right now
Application-level steps for this error.
- Use a wider integer type (integer or bigint) if values can legitimately exceed smallint's range.
- Validate expected value ranges in the application before inserting.
- Remember arithmetic on in-range values can still overflow the result type, see the premium counterexample below.
-- widen the type so a legitimately larger value fits
ALTER TABLE metrics.counters ALTER COLUMN count TYPE integer;
INSERT INTO metrics.counters (id, count) VALUES (5, 40000);For this error
See this error live on the server
Run these against the affected instance to confirm the diagnosis before you act.
Numeric value out of range is a mismatch between the bound value and the target type. Inspect the target definition, then log the rejected value at the application boundary.
Numeric precision/scale and integer target types
Find the target columns whose declared limits can produce this SQLSTATE.
SELECT table_schema, table_name, column_name, data_type,
numeric_precision, numeric_scale
FROM information_schema.columns
WHERE data_type IN ('smallint','integer','bigint','numeric','decimal')
ORDER BY table_schema, table_name, ordinal_position
LIMIT 100;Why it happens
What PostgreSQL is telling you
The mechanism behind the error, grounded in the official manual, not paraphrased.
PostgreSQL 16 Documentation, §8.1.1 Integer Types
Attempts to store values outside of the allowed range will result in an error.Read the full section on postgresql.org →
The insert that's out of range
40000 is past smallint's documented maximum of 32767, so PostgreSQL rejected the insert immediately.Checking the table afterward
The table is empty. The rejected insert left nothing behind, not even a clamped value.Reproduce & verify
A real, single-session PostgreSQL reproduction
A literal transcript of SQL run against a live PostgreSQL instance in an isolated lab. The commands below are exactly what was executed.
- 1Create a table with a smallint column.
- 2Insert a value outside smallint's documented range (-32768 to +32767).
- 3PostgreSQL rejects it with SQLSTATE 22003.
One client: create a smallint column, insert a value past its documented range.
CREATE SCHEMA IF NOT EXISTS metrics;
DROP TABLE IF EXISTS metrics.counters;
CREATE TABLE metrics.counters (
id integer primary key,
count smallint
);INSERT INTO metrics.counters (id, count) VALUES (1, 40000);SELECT * FROM metrics.counters;What PostgreSQL actually returned
DROP TABLE
CREATE TABLEERROR: smallint out of range id | count
----+-------
(0 rows)The documented boundary was tested at both ends: 32767 and -32768 are proven to be accepted exactly, and 32768, one past the upper boundary, is proven to be rejected.
Without this
Above: 40000 (well past the range) is rejected.
With this, tested
Below: the exact boundary values 32767 and -32768 succeed; 32768, one past the boundary, fails.
- A second operational test: exact SQL, raw output, measured result, and engineer notes
- Fix that looks safe but doesn't cover arithmetic: exact SQL, output, and verdict
- A manual-grounded production interpretation of the lab result
Card required. Cancel before day 7 and you are not charged.
Runbook to fix this
The runbook for this incident
Full step-by-step fixes for the condition behind this error: the diagnosis, the exact SQL, and output captured in the lab.
Connected
Everything this error touches
Every page this SQLSTATE connects to: the concept that explains it, the runbooks that fix it, the parameters you tune to prevent it, and the sibling errors it travels with. All real cross-references. Jump straight in, or open the full interactive map.
Verification
- Last verified
- 2026-07-16 (Docker lab, PostgreSQL 16.14)
- Verification scope
- Verified against PostgreSQL 16.14 in an isolated lab environment
- Audit status
- reviewed
Went further?
Pro unlocks the second lab proof
Free page stops the bleeding. Pro adds the operational test, SQLSTATE audit, and deeper evidence, same error, more certainty.