Errore PostgreSQL: current transaction is aborted
ERROR: current transaction is aborted, commands ignored until end of transaction block
Questo errore non è mai la causa radice. Qualche statement precedente nella stessa transazione è già fallito, la transazione è entrata nello stato aborted, e PostgreSQL ora rifiuta ogni comando successivo finché non termini la transazione con ROLLBACK. La domanda a cui rispondere è sempre: qual è stato il primo errore?
Cosa significa questo errore
Una volta che uno statement dentro una transazione fallisce, PostgreSQL garantisce che la transazione nel suo complesso non possa fare commit — consentire ad altri statement di "riuscire" ti permetterebbe di committare un'unità di lavoro applicata a metà. Quindi li rifiuta tutti, ripetendo questo messaggio, finché l'applicazione non emette ROLLBACK (o non fa rollback a un savepoint preso prima del fallimento).
Se vedi valanghe di 25P02 nei tuoi log, leggile come un sintomo a due strati: un errore originale (una riga, facile da mancare) e un'applicazione che ha continuato a usare la connessione come se nulla fosse (la valanga).
Cause comuni
- L'applicazione ingoia la prima eccezione — un try/catch che logga e continua, ancora dentro la transazione, ancora sulla stessa connessione.
- Codice di framework o driver che non fa rollback in caso di errore prima di riutilizzare la sessione.
- Un connection pool che consegna una connessione bloccata in una transazione fallita perché non resetta lo stato al rilascio.
- Script psql in esecuzione dentro
BEGIN ... COMMITche proseguono oltre un errore (di default psql continua).
Come diagnosticarlo
- Nel log del server, guarda cosa ha fatto la stessa sessione appena prima della valanga di 25P02 — con
%p(pid) inlog_line_prefixpuoi seguire la sessione; il primoERRORda quel pid è il tuo vero problema. - Nell'applicazione, logga e ispeziona la prima eccezione, non quelle successive: un abbinamento molto comune è una violazione di chiave duplicata seguita da un flusso di 25P02 da codice che l'ha "gestita" ed è andato avanti.
- Interattivamente in psql l'errore originale è semplicemente quello stampato appena sopra.
Come risolverlo
- A ogni errore di uno statement, fai rollback — poi riprova l'intera transazione se appropriato. Struttura il codice in modo che un'eccezione dentro una transazione non possa essere catturata senza terminare la transazione.
- Fallimenti attesi → savepoint, così un fallimento non avvelena la transazione:
Meglio ancora, quando il fallimento atteso è un duplicato, usaBEGIN; SAVEPOINT attempt; INSERT INTO users ...; -- può fallire -- in caso di errore: ROLLBACK TO SAVEPOINT attempt; -- la transazione resta utilizzabile COMMIT;ON CONFLICTed evita del tutto l'errore. - Script: esegui psql con
ON_ERROR_STOP(psql -v ON_ERROR_STOP=1) così un errore ferma lo script invece di cascare; interattivamente,\set ON_ERROR_ROLLBACK interactivefa sì che psql avvolga gli statement in savepoint per te. - Pool: assicurati che le connessioni siano sottoposte a rollback / reset (es.
DISCARD ALL) quando restituite al pool.
