Riferimento errori PostgreSQL

Gli errori che PostgreSQL ti lancia davvero in produzione, una pagina ciascuno: cosa significa il messaggio, le cause tipiche, come diagnosticarlo e come risolverlo — con comandi reali, senza giri di parole.

Connessioni e autenticazione

SQLSTATE 53300

too many clients

max_connections è esaurito. Come vedere chi tiene gli slot e perché la vera soluzione di solito è un connection pooler, non un limite più alto.

Connessioni

connection refused

La connessione TCP non ha mai raggiunto PostgreSQL. Server spento, porta sbagliata, listen_addresses, firewall o networking Docker — in quest'ordine.

SQLSTATE 28P01

password authentication failed

A volte la password è davvero sbagliata. Le altre volte: il ruolo non ha password, mismatch SCRAM/md5, o una URI che richiedeva il percent-encoding.

SQLSTATE 28000

no pg_hba.conf entry

Il server è raggiungibile ma nessuna regola pg_hba.conf corrisponde alla tua combinazione (host, database, user, SSL). L'errore ti dice esattamente quale.

SQLSTATE 3D000

database does not exist

Spesso il database indicato nell'errore è il tuo stesso username — il default di psql quando non ne specifichi uno. Oppure sei del tutto sulla porta sbagliata.

SQLSTATE 28000

role does not exist

Installazione nuova, e PostgreSQL non sa chi sia "ubuntu". Perché compare lo username OS, e come fare il bootstrap dei ruoli come si deve.

SQLSTATE 08006

server closed the connection

O il processo del server è morto (il log lo dirà) o un firewall/NAT ha silenziosamente tagliato una connessione idle (il log tacerà). Controlla prima il log.

Concorrenza e lock

SQLSTATE 40P01

deadlock detected

Due transazioni tengono ciascuna un lock che serve all'altra. Perché succede, come leggere le righe DETAIL e le abitudini di ordinamento dei lock che lo prevengono.

SQLSTATE 40001

could not serialize access

Repeatable Read o Serializable si è rifiutato di far finta che due transazioni in conflitto siano avvenute entrambe. Non è un bug — ma il tuo codice deve riprovare.

SQLSTATE 25P02

current transaction is aborted

Mai il vero problema: uno statement precedente nella transazione è già fallito, e PostgreSQL rifiuta tutto finché non fai ROLLBACK.

SQLSTATE 55P03

lock timeout

Lo statement ha rinunciato ad aspettare un lock — perché qualcuno ha sensatamente impostato lock_timeout. Trova chi blocca, e mantieni il pattern fail-fast.

SQLSTATE 40001

conflict with recovery

Solo sui replica: il replay del WAL doveva rimuovere versioni di riga che la tua query stava ancora usando. La soluzione è un compromesso che devi scegliere consapevolmente.

Vincoli e integrità dei dati

SQLSTATE 23505

duplicate key value

Un vincolo di unicità ha fatto il suo lavoro. La domanda interessante è perché: una race sull'insert, una sequence lasciata indietro da un import o un client che riprova.

SQLSTATE 23502

not-null violation

Una colonna NOT NULL sarebbe rimasta vuota. La variante subdola: il tuo ORM invia un NULL esplicito, che sovrascrive il DEFAULT della colonna.

SQLSTATE 23503

foreign key violation

Due direzioni, un vincolo: un figlio che punta a un padre mancante, o un padre in cancellazione mentre dei figli lo referenziano ancora.

SQLSTATE 22P02

invalid input syntax

Un valore testuale non è stato interpretabile come il tipo di destinazione. Di solito un cast su dati sporchi, una stringa vuota dove serviva un numero, o un header CSV.

SQLSTATE 22001

value too long

I dati hanno superato un limite varchar(n) e PostgreSQL rifiuta di troncare silenziosamente. Spesso la vera soluzione è mettere in discussione l'(n) stesso.

SQLSTATE 22012

division by zero

Un denominatore è arrivato a zero — di solito un gruppo vuoto in un'aggregazione. La soluzione da una riga da memorizzare: NULLIF(denominatore, 0).

SQLSTATE 42P10

no constraint matching ON CONFLICT

ON CONFLICT ha bisogno di un indice unique esattamente sulle colonne (o espressione, o predicato parziale) che hai indicato. Un indice normale non conta.

SQL, tipi e schema

SQLSTATE 42501

permission denied

Al tuo ruolo manca un privilegio — spesso perché le tabelle sono state create dal ruolo delle migrazioni e nessuno ha concesso nulla al ruolo applicativo su di esse.

SQLSTATE 42P01

relation does not exist

La tabella esiste — semplicemente non stai guardando dove guarda PostgreSQL. search_path, identificatori quotati e database sbagliato, in quest'ordine.

SQLSTATE 42703

column does not exist

Tre trappole causano la maggior parte di questi: colonne camelCase che vanno quotate, "stringhe" tra doppi apici (quelli sono identificatori!), e alias in WHERE.

SQLSTATE 42601

syntax error at or near

Il caret punta dove il parser si è arreso — l'errore di solito è lì o appena prima. Parole riservate e sintassi MySQL sono in cima alla lista.

SQLSTATE 42883

function does not exist

Leggilo come: nessuna funzione con quel nome e quei tipi di argomento. La funzione di solito esiste — sono i tuoi argomenti a essere del tipo sbagliato.

SQLSTATE 42803

must appear in GROUP BY

Hai selezionato una colonna che non è né raggruppata né aggregata. Spesso l'intento reale è "la riga più recente per gruppo" — che vuole DISTINCT ON, non GROUP BY.

SQLSTATE 21000

more than one row returned

Una subquery scalare prometteva al più una riga e ne ha consegnate diverse. O intendevi IN — oppure i tuoi dati hanno duplicati che non dovrebbero esserci.

Risorse e operazioni

SQLSTATE 57014

statement timeout

Una query ha sforato statement_timeout. Scopri se era lenta, bloccata su un lock, o se il timeout era impostato da qualche parte che avevi dimenticato.

SQLSTATE 53200

out of shared memory

Nonostante il nome spaventoso, è quasi sempre la tabella dei lock condivisa che si riempie — tipicamente una transazione che tocca migliaia di partizioni.

SQLSTATE 53100

no space left on device

Il disco è pieno — e sugli host PostgreSQL il colpevole è spesso il WAL trattenuto da un replication slot morto. Regola uno: mai cancellare a mano dalla directory dei dati.

Operazioni

wraparound protection

Il freno d'emergenza dell'MVCC: transaction ID quasi esauriti perché il freezing è rimasto indietro. Trova cosa ha bloccato il vacuum, poi lascialo recuperare.

Trovare il SQLSTATE di un errore

Ogni errore PostgreSQL porta con sé un codice SQLSTATE di cinque caratteri, più stabile del testo del messaggio (ed è ciò che il driver espone per la gestione programmatica). In psql, esegui \set VERBOSITY verbose e il codice viene stampato con ogni errore; nel codice applicativo, leggi il campo SQLSTATE dall'oggetto errore del tuo driver. Le pagine qui sopra indicano il SQLSTATE corrispondente a ciascun errore.