PostgreSQL error reference

The errors PostgreSQL actually throws at you in production, one page each: what the message means, the typical causes, how to diagnose it and how to fix it — with real commands, not hand-waving.

Connections & authentication

SQLSTATE 53300

too many clients

max_connections is exhausted. How to see who is holding the slots, and why the real fix is usually a connection pooler, not a bigger limit.

Connections

connection refused

The TCP connection never reached PostgreSQL at all. Server down, wrong port, listen_addresses, firewall or Docker networking — in that order.

SQLSTATE 28P01

password authentication failed

Sometimes the password really is wrong. The other times: the role has no password, SCRAM/md5 mismatch, or a URI that needed percent-encoding.

SQLSTATE 28000

no pg_hba.conf entry

The server is reachable but no pg_hba.conf rule matches your (host, database, user, SSL) combination. The error tells you exactly which.

SQLSTATE 3D000

database does not exist

Often the database named in the error is your own username — psql's default when you don't specify one. Or you're on the wrong port entirely.

SQLSTATE 28000

role does not exist

Fresh install, and PostgreSQL doesn't know who "ubuntu" is. Why the OS username shows up, and how to bootstrap roles properly.

SQLSTATE 08006

server closed the connection

Either the server process died (the log will say) or a firewall/NAT silently cut an idle connection (the log will be silent). Check the log first.

Concurrency & locks

SQLSTATE 40P01

deadlock detected

Two transactions each hold a lock the other needs. Why it happens, how to read the DETAIL lines, and the lock-ordering habits that prevent it.

SQLSTATE 40001

could not serialize access

Repeatable Read or Serializable refused to pretend two conflicting transactions both happened. Not a bug — but your code must retry.

SQLSTATE 25P02

current transaction is aborted

Never the real problem: an earlier statement in the transaction already failed, and PostgreSQL is refusing everything until you ROLLBACK.

SQLSTATE 55P03

lock timeout

The statement gave up waiting for a lock — because someone sensibly set lock_timeout. Find the blocker, and keep the fail-fast pattern.

SQLSTATE 40001

conflict with recovery

Only on replicas: WAL replay needed to remove row versions your query was still using. The fix is a trade-off you must choose consciously.

Constraints & data integrity

SQLSTATE 23505

duplicate key value

A unique constraint did its job. The interesting question is why: an insert race, a sequence left behind by an import, or a client retrying.

SQLSTATE 23502

not-null violation

A NOT NULL column would end up empty. The sneaky variant: your ORM sends an explicit NULL, which overrides the column's DEFAULT.

SQLSTATE 23503

foreign key violation

Two directions, one constraint: a child pointing at a missing parent, or a parent being deleted while children still reference it.

SQLSTATE 22P02

invalid input syntax

A text value could not be parsed as the target type. Usually a cast on dirty data, an empty string where a number was expected, or a CSV header.

SQLSTATE 22001

value too long

Data exceeded a varchar(n) limit and PostgreSQL refuses to truncate silently. Often the real fix is questioning the (n) itself.

SQLSTATE 22012

division by zero

A denominator hit zero — usually an empty group in an aggregation. The one-line fix worth memorizing: NULLIF(denominator, 0).

SQLSTATE 42P10

no constraint matching ON CONFLICT

ON CONFLICT needs a unique index on exactly the columns (or expression, or partial predicate) you named. A regular index does not count.

SQL, types & schema

SQLSTATE 42501

permission denied

Your role lacks a privilege — often because tables were created by the migration role and nobody granted the app role anything on them.

SQLSTATE 42P01

relation does not exist

The table exists — you're just not looking where PostgreSQL is looking. search_path, quoted identifiers and wrong-database, in that order.

SQLSTATE 42703

column does not exist

Three traps cause most of these: camelCase columns needing quotes, double-quoted "strings" (those are identifiers!), and aliases in WHERE.

SQLSTATE 42601

syntax error at or near

The caret points where the parser gave up — the mistake is usually at or just before it. Reserved words and MySQL syntax top the list.

SQLSTATE 42883

function does not exist

Read it as: no function with that name and those argument types. The function usually exists — your arguments are the wrong type.

SQLSTATE 42803

must appear in GROUP BY

You selected a column that is neither grouped nor aggregated. Often the real intent is "latest row per group" — which wants DISTINCT ON, not GROUP BY.

SQLSTATE 21000

more than one row returned

A scalar subquery promised at most one row and delivered several. Either you meant IN — or your data has duplicates it should not have.

Resources & operations

SQLSTATE 57014

statement timeout

A query blew past statement_timeout. Find out whether it was slow, blocked on a lock, or the timeout was set somewhere you forgot about.

SQLSTATE 53200

out of shared memory

Despite the scary name, it's almost always the shared lock table filling up — typically one transaction touching thousands of partitions.

SQLSTATE 53100

no space left on device

The disk is full — and on PostgreSQL hosts the culprit is often WAL retained by a dead replication slot. Rule one: never hand-delete from the data directory.

Operations

wraparound protection

The emergency brake of MVCC: transaction IDs nearly exhausted because freezing fell behind. Find what blocked vacuum, then let it catch up.

Finding the SQLSTATE of any error

Every PostgreSQL error carries a five-character SQLSTATE code, which is stabler than the message text (and what your driver exposes for programmatic handling). In psql, run \set VERBOSITY verbose and the code is printed with each error; in application code, read the SQLSTATE field from your driver's error object. The pages above list the SQLSTATE each error corresponds to.