A floating point exception in PostgreSQL typically occurs due to division by zero or invalid arithmetic operations. This can be prevented by adding guards in your SQL queries to check for zero denominators before performing division.
A floating point exception (error code 22P01 in PostgreSQL) is a fatal arithmetic error that occurs when the database engine encounters an invalid mathematical operation. This includes division by zero, overflow (result too large to represent), underflow (result too small), or other undefined mathematical operations. Although the name suggests floating-point operations, the error can occur with any numeric type including integers. The error causes the current statement to fail and typically rolls back the active transaction.
Use the NULLIF() function to return NULL when the divisor equals zero, which avoids the exception entirely:
-- Instead of this (will error if amount is 0):
SELECT total / amount FROM sales;
-- Use this:
SELECT total / NULLIF(amount, 0) FROM sales;This approach leverages the fact that dividing by NULL returns NULL rather than an error.
For more complex logic, wrap the division in a CASE statement:
SELECT
CASE
WHEN amount = 0 THEN 0
ELSE total / amount
END AS ratio
FROM sales;This gives you control over what value to return when division is invalid, such as 0, NULL, or a default value.
When NULLIF() returns NULL, use COALESCE() to supply a default:
SELECT
COALESCE(total / NULLIF(amount, 0), 0) AS ratio
FROM sales;This ensures your result is always a number rather than potentially NULL, useful when you need a specific default for undefined calculations.
If the error occurs with currency or financial calculations, use NUMERIC type instead of REAL or DOUBLE PRECISION:
ALTER TABLE sales
ALTER COLUMN amount TYPE NUMERIC(10,2);NUMERIC provides exact decimal arithmetic without floating-point rounding errors. It also has a larger safe range for calculations.
Verify that column values fall within acceptable ranges before use:
ALTER TABLE sales
ADD CONSTRAINT amount_positive CHECK (amount > 0);Preventing zero or invalid values from entering the database eliminates the root cause. For existing data, first identify problematic rows:
SELECT * FROM sales WHERE amount = 0 OR amount IS NULL;After applying guards, test with the exact queries and data that caused the error:
-- Identify the problematic query
SELECT total / NULLIF(amount, 0) AS ratio
FROM sales
WHERE amount = 0; -- This now returns NULL instead of errorVerify the result is NULL, 0, or your chosen default rather than an exception.
Understanding the underlying cause helps prevent recurrence:
Overflow Protection: For aggregate functions like SUM(), cast to a larger type if needed: SUM(amount)::DOUBLE PRECISION / COUNT(*)
Modulo Operations: The % operator also fails with zero divisors. Guard it the same way: column % NULLIF(divisor, 0)
Performance: CASE statements can be slower than simple NULLIF for large datasets. Profile both approaches on your data.
Type Selection: NUMERIC is slower but exact (use for money). DOUBLE PRECISION is faster but subject to rounding and overflow (use for scientific data). REAL is fastest but least precise.
Application-Level Handling: If division is application logic, consider moving the check to your code rather than the database to reduce round-trips and errors.
Compiler Bugs: Historically, PostgreSQL on some systems could report "floating point exception" for division by zero on integer types due to compiler bugs. Update PostgreSQL if the error persists on simple integer division.
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