PostgreSQL error: current transaction is aborted
ERROR: current transaction is aborted, commands ignored until end of transaction block
This error is never the root cause. Some earlier statement in the same transaction already failed, the transaction entered the aborted state, and PostgreSQL now rejects every further command until you end the transaction with ROLLBACK. The question to answer is always: what was the first error?
What this error means
Once any statement inside a transaction fails, PostgreSQL guarantees the transaction as a whole cannot commit — allowing further statements to "succeed" would let you commit a half-applied unit of work. So it refuses them all, repeating this message, until the application issues ROLLBACK (or rolls back to a savepoint taken before the failure).
If you're seeing floods of 25P02 in your logs, read them as a symptom with two layers: an original error (one line, easy to miss) and an application that kept using the connection as if nothing happened (the flood).
Common causes
- The application swallows the first exception — a try/catch that logs and continues, still inside the transaction, still on the same connection.
- Framework or driver code that doesn't roll back on error before reusing the session.
- A connection pool handing out a connection stuck in a failed transaction because it doesn't reset state on release.
- psql scripts running inside
BEGIN ... COMMITthat continue past an error (by default psql keeps going).
How to diagnose it
- In the server log, look at what the same session did just before the 25P02 flood — with
%p(pid) inlog_line_prefixyou can follow the session; the firstERRORfrom that pid is your real problem. - In the application, log and inspect the first exception, not the ones after it: a very common pairing is a duplicate key violation followed by a stream of 25P02 from code that "handled" it and moved on.
- Interactively in psql the original error is simply the one printed right above.
How to fix it
- On any statement error, roll back — then retry the whole transaction if appropriate. Structure code so an exception inside a transaction cannot be caught without ending the transaction.
- Expected failures → savepoints, so one failure doesn't poison the transaction:
Better yet, when the expected failure is a duplicate, useBEGIN; SAVEPOINT attempt; INSERT INTO users ...; -- può fallire -- in caso di errore: ROLLBACK TO SAVEPOINT attempt; -- la transazione resta utilizzabile COMMIT;ON CONFLICTand avoid the error entirely. - Scripts: run psql with
ON_ERROR_STOP(psql -v ON_ERROR_STOP=1) so an error stops the script instead of cascading; interactively,\set ON_ERROR_ROLLBACK interactivemakes psql wrap statements in savepoints for you. - Pools: make sure connections are rolled back / reset (e.g.
DISCARD ALL) when returned to the pool.
