When PostgreSQL raises a data-related error and no more-specific subclass code applies, you may see SQLSTATE 22000 with the condition name data_exception reported in your logs, application exception, or psql output:
ERROR: invalid input syntax for type integer: "abc"
SQLSTATE: 22000
More commonly you encounter a specific child code (e.g., 22001 string_data_right_truncation, 22003 numeric_value_out_of_range, 22P02 invalid_text_representation), but all of them share the 22 class prefix and are subtypes of data_exception.
What This Error Means
SQLSTATE codes are structured as a two-character class followed by a three-character subclass. Class 22 is defined by the SQL standard as the Data Exception class — a broad category covering situations where a value is incompatible with the target type or constraints imposed by a data operation (INSERT, UPDATE, CAST, function call, etc.).
PostgreSQL uses 22000 as the generic fallback within this class. In practice, PostgreSQL almost always raises a more specific subclass (see the table in Additional Information), so encountering bare 22000 typically means either a PL/pgSQL function raised a DATA EXCEPTION explicitly using RAISE SQLSTATE '22000', or an older version of PostgreSQL could not categorise the error more precisely.
When a data_exception is raised inside an explicit transaction block, the transaction is marked as aborted. All subsequent statements in that transaction will fail with ERROR: current transaction is aborted, commands ignored until end of transaction block until you issue a ROLLBACK or ROLLBACK TO SAVEPOINT. Outside a transaction block, the statement-level rollback is automatic and the connection remains usable.
Common Causes
- Explicit
RAISE SQLSTATE '22000'— A PL/pgSQL function or procedure usesRAISE EXCEPTION USING ERRCODE = '22000'(orSQLSTATE '22000') to signal a custom data validation failure. - Unrecognised subclass in an older PostgreSQL version — A data error occurred but the PostgreSQL version does not define a more specific subclass for the exact condition, so it falls back to the class-level code
22000. - Driver or client mapping — Some JDBC/ODBC drivers or client libraries collapse all
22xxxerrors to the base class22000when they do not recognise the specific subclass, making the generic code visible to the application even though PostgreSQL raised a specific subclass. - Application catching class-level codes — Application code that catches or logs by the first two characters of SQLSTATE (
22) may report22000as a label for any data exception, masking the real subclass.
How to Fix data_exception
Inspect the full error message and detail. PostgreSQL always includes a human-readable message alongside the SQLSTATE. The message text almost always identifies the offending value and the target type. Check your application logs, or in psql run
\errverboseimmediately after the error to see the full detail, hint, and context fields.Check the actual SQLSTATE subclass. If your client library or log aggregator is reporting
22000, confirm the real subclass emitted by PostgreSQL:-- In psql, see the exact code after triggering the error: \set VERBOSITY verbose SELECT '2023-02-30'::date;The verbose output will show the exact
SQLSTATEandLOCATIONin the source.If raised by a PL/pgSQL function, review the function source. Look for explicit
RAISEstatements that set SQLSTATE22000:-- Identify functions that raise 22000 directly SELECT proname, prosrc FROM pg_proc WHERE prosrc ILIKE '%22000%' AND prolang = (SELECT oid FROM pg_language WHERE lanname = 'plpgsql');Roll back the aborted transaction before retrying. If the error occurred inside a transaction block, the transaction must be rolled back before issuing any further statements:
ROLLBACK; -- or, if you used a savepoint: ROLLBACK TO SAVEPOINT my_savepoint;Fix the upstream data or query based on what the child SQLSTATE indicates. For example:
22001— truncate the string or widen the column.22003— reduce the numeric value or change the column type.22007/22008— correct the date/time format.22P02— fix the string-to-type cast (e.g., passing"abc"where an integer is expected).
Additional Information
Class
22contains over 30 specific subclasses. The most common ones you will encounter in practice:SQLSTATE Condition Name Typical Cause 22001 string_data_right_truncation Value too long for VARCHAR(n)column22003 numeric_value_out_of_range Value exceeds INTEGER/NUMERICrange22007 invalid_datetime_format Bad date/time literal string 22008 datetime_field_overflow Date like 2023-02-3022012 division_by_zero Divisor evaluates to zero 2200F zero_length_character_string Empty string where non-empty required 22P01 floating_point_exception NaN / infinity in a context that disallows it 22P02 invalid_text_representation Cannot cast text to target type 22P03 invalid_binary_representation Malformed binary format input In JDBC (pgjdbc), all class-22 errors are mapped to
java.sql.SQLDataException. ThegetSQLState()method returns the specific subclass code, not22000, unless PostgreSQL literally sent22000.In psycopg2 and psycopg3, class-22 errors raise
psycopg2.errors.DataError(or the specific subclass exception if one is defined in the module), accessible viaexception.pgcode.SQLAlchemy surfaces these as
sqlalchemy.exc.DataError, wrapping the underlying driver exception.SQLSTATE class
22errors are defined in the SQL:1999 standard and have been stable across all supported PostgreSQL versions (9.x through 17).
Frequently Asked Questions
Why does my application report 22000 but psql shows a different code?
Your client library or ORM is likely mapping the specific subclass (e.g., 22P02) up to the generic class code 22000. Check the raw getSQLState() / pgcode on the exception object, or enable verbose logging in your driver. Alternatively, enable log_min_messages = DEBUG1 temporarily in PostgreSQL and check pg_log for the exact SQLSTATE emitted.
Is 22000 a fatal error? Will it close my database connection?
No. Data exception errors are statement-level (or transaction-level if inside a transaction block). They do not terminate the connection. After a ROLLBACK (or outside an explicit transaction), the connection is fully reusable.
How do I catch only data_exception errors in PL/pgSQL?
Use the condition name directly in an EXCEPTION block:
BEGIN
-- ... your logic
EXCEPTION
WHEN data_exception THEN
-- handles 22000 and all 22xxx subclasses
RAISE NOTICE 'Data error: %', SQLERRM;
END;
Catching the parent condition data_exception also catches all its subclasses (22001, 22003, 22P02, etc.).
How do I raise a 22000 error intentionally from a function?
RAISE EXCEPTION 'Value % is not valid for this operation', input_value
USING ERRCODE = '22000';
Prefer a more specific subclass code when one exists, as it gives callers more actionable information.