The "Numeric value out of range" error occurs when a numeric value exceeds the valid range for its data type. This typically happens when inserting large numbers into INTEGER/BIGINT columns or when NUMERIC/DECIMAL precision is insufficient.
The "Numeric value out of range" error (SQLSTATE 22003) occurs when PostgreSQL attempts to store or process a numeric value that exceeds the valid range for the target data type. Each numeric type in PostgreSQL has specific minimum and maximum values it can represent. This error is most common with integer types (SMALLINT, INTEGER, BIGINT) when values exceed their boundaries, but can also occur with NUMERIC/DECIMAL types when the declared precision and scale are insufficient for the value being inserted or calculated. It can also happen during arithmetic operations that produce results outside the allowed range.
Check your error logs and application output to find the exact column and value. The PostgreSQL error message may include context about which query failed. For example:
ERROR: value "9999999999" is out of range for type integerThis tells you that 9999999999 exceeds the INTEGER type limit.
Connect to your database and verify the column definitions:
-- View table structure
\d table_name;
-- Or query information schema
SELECT column_name, data_type, numeric_precision, numeric_scale
FROM information_schema.columns
WHERE table_name = 'your_table';Reference the numeric type limits:
- SMALLINT: -32,768 to 32,767
- INTEGER (INT/INT4): -2,147,483,648 to 2,147,483,647
- BIGINT (INT8): -9,223,372,036,854,775,808 to 9,223,372,036,854,775,807
- NUMERIC(precision, scale): Up to 131,072 digits before decimal, 16,383 after
If you need to store larger values, change the column type. This is the most common fix:
-- Change INTEGER to BIGINT
ALTER TABLE table_name ALTER COLUMN column_name TYPE BIGINT;
-- Change NUMERIC precision
ALTER TABLE table_name ALTER COLUMN column_name TYPE NUMERIC(15, 2);
-- For SERIAL to BIGSERIAL, drop and recreate the sequence
ALTER TABLE table_name DROP CONSTRAINT table_name_id_key;
ALTER TABLE table_name ALTER COLUMN id TYPE BIGINT;
CREATE SEQUENCE table_name_id_seq AS BIGINT;
ALTER TABLE table_name ALTER COLUMN id SET DEFAULT nextval('table_name_id_seq');Test the change works before running in production.
For NUMERIC/DECIMAL columns used in calculations, ensure the precision is large enough for intermediate and final results:
-- Too small: NUMERIC(5, 2) can only hold values up to 999.99
ALTER TABLE table_name ALTER COLUMN price TYPE NUMERIC(10, 2); -- Now holds up to 99,999,999.99
-- For calculations, use a larger precision in intermediate steps
SELECT
id,
price,
quantity,
price * quantity AS total -- Ensure this fits in result column type
FROM orders;
-- Or cast to larger type during calculation
SELECT
id,
CAST(price AS NUMERIC(15, 2)) * CAST(quantity AS NUMERIC(15, 2)) AS total
FROM orders;Implement checks in your application before inserting values into the database:
// Node.js/JavaScript example
const MAX_INT = 2147483647;
const MIN_INT = -2147483648;
function validateIntegerColumn(value) {
if (value > MAX_INT || value < MIN_INT) {
throw new Error(`Value ${value} exceeds INTEGER range`);
}
return value;
}
// Or for NUMERIC columns
function validateNumeric(value, precision, scale) {
const maxIntegerDigits = precision - scale;
const maxValue = Math.pow(10, maxIntegerDigits) - 1;
if (Math.abs(value) >= maxValue) {
throw new Error(`Value exceeds NUMERIC(${precision}, ${scale}) range`);
}
return value;
}SERIAL vs BIGSERIAL: When creating new tables with auto-incrementing primary keys, prefer BIGSERIAL over SERIAL. SERIAL can only handle ~2 billion records, while BIGSERIAL supports ~9 quintillion records.
Sequence Wraparound: SERIAL sequences don't cycle by default. Once they reach their max value, subsequent nextval() calls will error. Monitor sequence values in high-volume tables: SELECT last_value FROM sequence_name;
Overflow in Calculations: Arithmetic operations like multiplication can produce temporary results that exceed column precision. Use intermediate casts to larger types when performing calculations: CAST(a AS NUMERIC(20,4)) * CAST(b AS NUMERIC(20,4))
Migration Safety: When altering large tables, PostgreSQL will rewrite the entire table, which can lock it temporarily. Consider using concurrent operations in production: ALTER TABLE ... ALTER COLUMN ... TYPE ... USING expression; with minimal locking strategies.
Float vs Numeric: Avoid REAL/DOUBLE PRECISION for financial data as they have rounding errors. NUMERIC stores exact decimal values at the cost of slightly more storage.
ERROR: syntax error at end of input
Syntax error at end of input in PostgreSQL
Bind message supplies N parameters but prepared statement requires M
Bind message supplies N parameters but prepared statement requires M in PostgreSQL
Multidimensional arrays must have sub-arrays with matching dimensions
Multidimensional arrays must have sub-arrays with matching dimensions
ERROR: value too long for type character varying
Value too long for type character varying
insufficient columns in unique constraint for partition key
How to fix "insufficient columns in unique constraint for partition key" in PostgreSQL