PostgreSQL Data Exception (SQLSTATE 22000)

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

  1. Explicit RAISE SQLSTATE '22000' — A PL/pgSQL function or procedure uses RAISE EXCEPTION USING ERRCODE = '22000' (or SQLSTATE '22000') to signal a custom data validation failure.
  2. 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.
  3. Driver or client mapping — Some JDBC/ODBC drivers or client libraries collapse all 22xxx errors to the base class 22000 when they do not recognise the specific subclass, making the generic code visible to the application even though PostgreSQL raised a specific subclass.
  4. Application catching class-level codes — Application code that catches or logs by the first two characters of SQLSTATE (22) may report 22000 as a label for any data exception, masking the real subclass.

How to Fix data_exception

  1. 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 \errverbose immediately after the error to see the full detail, hint, and context fields.

  2. 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 SQLSTATE and LOCATION in the source.

  3. If raised by a PL/pgSQL function, review the function source. Look for explicit RAISE statements that set SQLSTATE 22000:

    -- 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');
    
  4. 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;
    
  5. 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 22 contains 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) column
    22003 numeric_value_out_of_range Value exceeds INTEGER / NUMERIC range
    22007 invalid_datetime_format Bad date/time literal string
    22008 datetime_field_overflow Date like 2023-02-30
    22012 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. The getSQLState() method returns the specific subclass code, not 22000, unless PostgreSQL literally sent 22000.

  • In psycopg2 and psycopg3, class-22 errors raise psycopg2.errors.DataError (or the specific subclass exception if one is defined in the module), accessible via exception.pgcode.

  • SQLAlchemy surfaces these as sqlalchemy.exc.DataError, wrapping the underlying driver exception.

  • SQLSTATE class 22 errors 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.

Subscribe to the Pulse Newsletter

Get early access to new Pulse features, insightful blogs & exclusive events , webinars, and workshops.

We use cookies to provide an optimized user experience and understand our traffic. To learn more, read our use of cookies; otherwise, please choose 'Accept Cookies' to continue using our website.