Error reference
Start with an incident, then inspect the evidence
All 100 errors are reproduced in a Docker lab and cited to the official manual. 85 carry full Pro lab evidence — the exact SQL, the raw psql output, and the concurrency proof. Prefer the map? See the SQLSTATE reference.
Showing 100 of 100 errors
Could not serialize access due to concurrent update
The REPEATABLE READ concurrent-update form of SQLSTATE 40001: a REPEATABLE READ transaction attempted to update a row that a concurrently committed transaction had already changed. This page scopes to that exact form — the one reproduced in the lab below, not the general SERIALIZABLE case.
Deadlock detected
Two or more transactions waited on locks held by each other, forming a cycle. PostgreSQL detected the deadlock and aborted one transaction so the others could continue.
Duplicate key value violates unique constraint
A row was inserted with a value that a unique column already has. PostgreSQL blocked the insert so the unique constraint stays true.
Current transaction is aborted, commands ignored until end of transaction block
One statement inside a transaction failed. PostgreSQL now rejects every later command in that same transaction until it sees ROLLBACK, even if those later commands are perfectly valid on their own.
Null value in column violates not-null constraint
A column was declared NOT NULL, and an INSERT or UPDATE tried to leave it null anyway. PostgreSQL rejects the row before it is ever stored.
Insert or update violates foreign key constraint
A row referenced a value in another table through a FOREIGN KEY, but that value doesn't exist there. PostgreSQL rejects the row to keep the two tables consistent.
New row violates check constraint
A column or table has a CHECK constraint, and an INSERT or UPDATE produced a row where that check evaluated to false. PostgreSQL rejects the row.
New row violates exclusion constraint
A table has an EXCLUDE constraint, and a new row conflicts with an existing row under the constraint's comparison — most commonly, two overlapping time ranges for the same resource.
Division by zero
An expression divided a number by zero. PostgreSQL raises an error instead of returning infinity or an undefined result.
Could not obtain lock on row
A session asked to lock a row with NOWAIT, but another session already had that row locked. Instead of waiting, PostgreSQL said no right away.
Value too long for character varying(n)
A string was too long to fit in a length-limited column. PostgreSQL rejects it — except in one narrow case the manual calls out by name.
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.
Relation does not exist
A query referenced a table that PostgreSQL couldn't find. Usually a typo — but the table can also just be in a schema that isn't being searched.
Column does not exist
A query referenced a column name PostgreSQL couldn't find on that table. Usually a typo — PostgreSQL often suggests the real name in a HINT.
More than one row returned by a subquery used as an expression
A scalar subquery matched more than one row. PostgreSQL only allows a scalar subquery to return exactly one row, so it rejects the query.
UNION types cannot be matched
A UNION mixed two branches whose types can't be converted to each other. PostgreSQL resolves UNIONs two branches at a time, so where a mismatch appears in that chain matters.
Function does not exist
A function was called with an argument type it doesn't accept. PostgreSQL's overload resolution found no match, rather than silently coercing to something close.
Invalid input syntax
A string literal was cast to a type whose input function couldn't parse it. PostgreSQL rejected the value outright rather than guessing at a conversion.
Relation already exists
A CREATE TABLE named a relation that already exists. PostgreSQL refused to create a second object under the same name instead of silently overwriting it.
Permission denied
A role tried to use a table it has not been granted privileges on. PostgreSQL denied the action instead of falling back to the owner's or a broader role's access.
Syntax error
PostgreSQL's parser rejected the statement because it didn't match valid SQL grammar — here, an unquoted reserved key word used as a table name.
Duplicate object
A CREATE ROLE named a role that already exists. PostgreSQL refused to create a second role under the same name.
Cannot coerce
A value was cast to a type with no defined conversion path. PostgreSQL refused the cast instead of guessing at one.
No active SQL transaction
A command that only makes sense inside an open transaction block was issued with none active. PostgreSQL rejected it instead of silently ignoring it.
Read-only SQL transaction
A write was attempted inside a transaction explicitly marked READ ONLY. PostgreSQL blocked the write instead of allowing it.
Active SQL transaction
VACUUM (and a few other commands) refuse to run while a transaction block is still open. PostgreSQL rejected the command instead of running it partway.
Object in use
A DROP DATABASE was attempted while another session was still connected to that database. PostgreSQL refused to drop it out from under an active connection.
Query canceled
A statement ran longer than the configured statement_timeout, and PostgreSQL canceled it. This is PostgreSQL enforcing a time limit you set, not a crash.
Invalid password
A connection attempt supplied the wrong password for a password-authenticated role. PostgreSQL rejected the connection before it was ever established.
Invalid catalog name
A connection attempt named a database that doesn't exist. PostgreSQL rejected the connection before it was ever established.
Invalid datetime format
A text value was cast to a date/time type, but PostgreSQL couldn't parse it as any recognized date/time format at all.
Datetime field overflow
A date/time value was well-formed text, but named a value that doesn't exist on the calendar or falls outside PostgreSQL's supported range.
String data length mismatch
A bit string value was stored into a bit(n) column whose length didn't exactly match n. PostgreSQL rejected the write instead of guessing how to fit it.
Invalid regular expression
A regular expression pattern passed to a PostgreSQL function was not valid — usually unbalanced parentheses or brackets. PostgreSQL refused to compile it.
Undefined parameter
A query referenced a positional parameter ($1, $2, ...) outside of any context that supplies a value for it. PostgreSQL had nothing to substitute.
Null value not allowed
A PL/pgSQL variable declared NOT NULL was assigned a null value. PostgreSQL rejected the assignment instead of silently storing null.
Idle in transaction session timeout
A session left an open transaction sitting idle (no query in flight) for longer than idle_in_transaction_session_timeout. PostgreSQL terminated the connection instead of letting it hold locks and a snapshot indefinitely.
Dependent objects still exist
A DROP ROLE was attempted while that role still owned a table. PostgreSQL refused to drop the role rather than leave an object without a valid owner.
Raise exception
PL/pgSQL code called RAISE EXCEPTION with no explicit error code. PostgreSQL reported it under the default PL/pgSQL error code, P0001, and aborted the transaction.
No data found
A PL/pgSQL SELECT ... INTO STRICT found zero matching rows. PostgreSQL raised an error instead of silently leaving the target null.
Unique constraint on partitioned table
A UNIQUE constraint was added to a partitioned table without including all of the partition key columns. PostgreSQL rejected it because it cannot enforce uniqueness across partitions.
COPY FREEZE with prior transaction activity
COPY ... WITH (FREEZE) was attempted while a cursor was still open in the same transaction. PostgreSQL refused because it can no longer guarantee no one else can see the pre-freeze rows.
Bind message parameter mismatch
A Bind message in the extended query protocol supplied a different number of parameter values than the prepared statement expected. PostgreSQL rejected it as a protocol violation.
Connection to client lost
A client was abruptly killed mid-query, severing the connection while the server still had output to send. PostgreSQL logged SQLSTATE 08006 and cleaned up that backend.
Too many connections
A non-superuser connection attempt arrived after every non-reserved connection slot was already in use. PostgreSQL rejected it so the reserved slots stay available for superuser roles.
date_trunc invalid field
date_trunc() was called with a field name it doesn't recognize. PostgreSQL rejected the call instead of guessing what precision was meant.
Schema does not exist
A CREATE TABLE statement referenced a schema name that doesn't exist yet. PostgreSQL rejected it instead of creating the schema implicitly.
Too many function arguments
A function was called with more positional arguments than PostgreSQL allows in a single call. PostgreSQL rejected the call at parse time.
Cannot change runtime parameter
A session tried to SET a parameter that can only be changed by restarting the server. PostgreSQL rejected the SET instead of silently ignoring it.
Too many rows
A PL/pgSQL SELECT ... INTO STRICT matched more than one row. PostgreSQL raised an error instead of silently picking one of them.
Column reference is ambiguous
A query referenced a bare column name that exists in more than one table in the FROM clause, so PostgreSQL could not tell which table you meant.
Column specified more than once
A CREATE TABLE listed the same column name twice. PostgreSQL refuses to build a table that has two columns with the same name.
Negative substring length not allowed
substring(... FOR count) was given a negative count. PostgreSQL treats a negative substring length as a data error rather than returning an empty string.
LIMIT must not be negative
A query passed a negative value to LIMIT. PostgreSQL requires LIMIT to be non-negative; use LIMIT ALL or NULL to mean “no limit”.
Cursor does not exist
A CLOSE (or FETCH/MOVE) named a cursor that was never declared, or was already closed. PostgreSQL has no OPEN statement — a cursor exists only once you DECLARE it.
Cannot insert a non-DEFAULT value into a GENERATED ALWAYS column
An INSERT supplied an explicit value for a GENERATED ALWAYS AS IDENTITY column. PostgreSQL only accepts a user value there when the statement says OVERRIDING SYSTEM VALUE.
Logarithm of a negative number
PostgreSQL raises this data exception when ln(), log(), or log(b, x) is asked for the logarithm of a value that is zero or negative, which is undefined for the real logarithm.
Zero raised to a negative power
power(0, n) with a negative exponent is undefined because it implies division by zero, so PostgreSQL raises this data exception instead of returning infinity.
width_bucket count must be positive
width_bucket(operand, low, high, count) requires the bucket count to be a positive integer; passing zero or a negative count raises this data exception.
Negative OFFSET in a query
The OFFSET clause must skip a non-negative number of rows; an OFFSET that evaluates to a negative value raises this data exception.
ntile argument must be positive
The ntile(n) window function divides rows into n ranked buckets and requires n to be a positive integer; zero or a negative bucket count raises this data exception.
nth_value argument must be positive
nth_value(expr, n) returns the value from the n-th row of the window frame and requires n to be a positive integer; zero or a negative position raises this data exception.
Negative window frame offset
A window frame's PRECEDING/FOLLOWING offset must be non-negative; a negative frame bound raises this data exception.
Interval field overflow
An INTERVAL literal whose field value exceeds the storage limits of the interval type raises this data exception; here a months value larger than a signed 32-bit integer overflowed.
Untranslatable character between encodings
Converting text to a target encoding fails when a character has no representation there; the euro sign (U+20AC) has no LATIN1 equivalent.
Invalid byte sequence for encoding
Interpreting bytes as text in a given encoding fails when the bytes are not valid there; 0xff is never a valid standalone UTF-8 byte.
Invalid LIKE ESCAPE string
The ESCAPE clause of LIKE accepts an empty string or exactly one character; a multi-character escape string raises this data exception.
COPY: extra data after last column
COPY fails when an input row has more fields than the target column list expects; a three-field, tab-separated line loaded into a narrower target raises this bad-copy-format error.
No SQL/JSON item for path (ON EMPTY)
JSON_VALUE raises this when the path matches nothing and the ON EMPTY behavior is ERROR; a DEFAULT ... ON EMPTY clause avoids it.
JSON_VALUE must return a single scalar
JSON_VALUE must resolve to a single scalar; a path that returns an array, object, or multiple items raises this data exception — use JSON_QUERY for non-scalars.
Time zone displacement out of range
A timestamptz literal whose explicit UTC offset lies outside the valid range (about -15:59 to +15:59) raises this data exception; +16:00 is out of range.
Sequence reached its maximum value
nextval() fails once a non-cycling sequence hits its MAXVALUE; a sequence capped at 2 raised the limit error on the third call.
Invalid XML document (DOCUMENT)
XMLPARSE(DOCUMENT ...) requires well-formed XML; mismatched opening and closing tags raise this data exception with a DETAIL pointing at the mismatch.
Invalid XML content (CONTENT)
XMLPARSE(CONTENT ...) still requires well-formed markup; an unclosed tag raises this data exception with a DETAIL about the premature end of data.
Invalid XML comment
xmlcomment() rejects text that would produce an illegal XML comment — XML comments cannot contain a double hyphen or end with a hyphen.
Invalid XML processing instruction
xmlpi() rejects an illegal processing-instruction target; the name 'xml' (in any case) is reserved and cannot be used as a target.
CASE not found (no matching branch)
A PL/pgSQL CASE statement with no matching WHEN and no ELSE raises this at runtime when the selector matches none of the branches.
Column must appear in GROUP BY
A non-aggregated column in the SELECT list of a grouped query must appear in GROUP BY or be wrapped in an aggregate; otherwise PostgreSQL raises this grouping error.
Wrong object type (DROP INDEX on a table)
Object-specific DDL like DROP INDEX only accepts that object type; running DROP INDEX against a table raises this wrong-object-type error with a hint to use DROP TABLE.
Undefined data type
Referencing a type that has not been created (or is misspelled or out of the search_path) raises this undefined-object error; 'currency' is not a built-in type.
ORDER BY position out of range
ORDER BY and GROUP BY can reference output columns by position, but the position must be within the select list; a position beyond the number of selected columns raises this error.
Index expression must be immutable
An expression index may only use IMMUTABLE functions, because a changing result would silently corrupt the index; a non-immutable function in the expression raises this error.
Multiple primary keys not allowed
A table can have at most one PRIMARY KEY; declaring PRIMARY KEY on two columns separately raises this invalid-table-definition error. Use a composite key for several columns.
Duplicate prepared statement
Preparing a statement with a name that is already prepared in the session raises this error; prepared-statement names must be unique per session.
Duplicate schema
CREATE SCHEMA fails if a schema of that name already exists; IF NOT EXISTS makes the creation idempotent.
Duplicate cursor
Declaring a cursor with a name already open in the same transaction raises this error; cursor names must be unique within a transaction.
Reserved schema name (pg_ prefix)
Schema names beginning with 'pg_' are reserved for system schemas; creating one raises this reserved-name error.
Duplicate function
CREATE FUNCTION fails when a function with the same name and argument types already exists; CREATE OR REPLACE updates it instead of colliding.
Duplicate table alias
Each table or alias in a FROM clause must have a unique name; using the same alias twice raises this duplicate-alias error.
No unique constraint for foreign key
A foreign key must reference columns backed by a PRIMARY KEY or UNIQUE constraint on the parent; referencing unconstrained columns raises this invalid-foreign-key error.
Collation mismatch (explicit collations)
A comparison cannot combine two different explicit COLLATE clauses; applying 'C' to one side and 'POSIX' to the other raises this collation-mismatch error.
Indeterminate collation
When PostgreSQL cannot derive a collation for a string operation, it raises this error and hints to add an explicit COLLATE clause.
Duplicate function parameter name
A function's named parameters must be distinct; declaring two parameters with the same name raises this invalid-function-definition error.
Prepared statement does not exist
EXECUTE or DEALLOCATE of a prepared-statement name that was never prepared (or was already deallocated) raises this invalid-statement-name error.
Function ended without RETURN
A function declared to return a value must execute a RETURN on every path; a code path that falls off the end without RETURN raises this SQL-routine exception at call time.
WITH CHECK OPTION violation
Writing through a view defined WITH CHECK OPTION fails when the new or updated row would fall outside the view's WHERE condition; the row must remain visible through the view.
ROLLBACK TO an undeclared savepoint
ROLLBACK TO SAVEPOINT (or RELEASE SAVEPOINT) fails if the named savepoint was never established in the current transaction, raising this savepoint exception.
PL/pgSQL assertion failure
A PL/pgSQL ASSERT whose condition evaluates to false raises this error with the assertion's message; it signals a violated invariant, not ordinary data validation.
RESTRICT foreign-key violation
Deleting or updating a parent row referenced by a child fails when the foreign key uses RESTRICT (or NO ACTION with a still-present child); the referencing rows must go first.
GET STACKED DIAGNOSTICS outside a handler
GET STACKED DIAGNOSTICS reads details of the exception currently being handled, so it is only valid inside an EXCEPTION handler; using it elsewhere raises this diagnostics exception.