Error reference
Start with an incident, then inspect the evidence
All 56 errors are reproduced in a Docker lab and cited to the official manual. 41 carry full Pro lab evidence — the exact SQL, the raw psql output, and the concurrency proof. Prefer the map? See the SQLSTATE reference.
Showing 56 of 56 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.