25P02
PostgreSQLERRORCommonInvalid Transaction StateHIGH confidence

current transaction is aborted, commands ignored until end of transaction block

What this means

A previous statement in the current transaction block raised an error and aborted the transaction. Postgres refuses to execute any further statements until the transaction is explicitly rolled back with ROLLBACK or ROLLBACK TO SAVEPOINT.

Why it happens
  1. 1A statement inside a BEGIN...COMMIT block raised any error (even 22001 or 42703)
  2. 2The application continues sending queries after catching an error without rolling back
  3. 3A PL/pgSQL function raised an exception that was not caught within a sub-block
How to reproduce

A failed statement inside a transaction leaves it in an aborted state; a subsequent statement triggers 25P02.

trigger — this will error
trigger — this will error
BEGIN;
INSERT INTO users (email) VALUES (NULL); -- raises 23502 (not-null violation)

-- Transaction is now aborted; next statement triggers 25P02:
SELECT * FROM users;

expected output

ERROR:  null value in column "email" of relation "users" violates not-null constraint
DETAIL:  Failing row contains (null).

ERROR:  current transaction is aborted, commands ignored until end of transaction block

Fix 1

ROLLBACK and retry the transaction

WHEN When the failed statement was not critical and the transaction should start fresh.

ROLLBACK and retry the transaction
ROLLBACK;

BEGIN;
INSERT INTO users (email) VALUES ('alice@example.com');
SELECT * FROM users;
COMMIT;

Why this works

ROLLBACK discards all changes made in the aborted transaction and releases all locks. The transaction state machine returns to IDLE, allowing new transactions to begin. The next BEGIN starts a fresh snapshot.

Fix 2

Use SAVEPOINT to recover from errors within a transaction

WHEN When partial work must be preserved and only the failed sub-operation should be rolled back.

Use SAVEPOINT to recover from errors within a transaction
BEGIN;
INSERT INTO audit_log (action) VALUES ('batch start');

SAVEPOINT before_risky;
INSERT INTO users (email) VALUES (NULL); -- will fail

ROLLBACK TO SAVEPOINT before_risky; -- undo only the failed insert

INSERT INTO users (email) VALUES ('alice@example.com'); -- retry with valid data
COMMIT;

Why this works

SAVEPOINT creates a sub-transaction snapshot. ROLLBACK TO SAVEPOINT restores the transaction state to the savepoint without rolling back the entire transaction. The outer transaction resumes in a valid (non-aborted) state, and subsequent statements execute normally.

What not to do

Continue sending queries after an error hoping they will execute

All statements after the first error in a transaction block are discarded until ROLLBACK; no work is done and the connection is blocked.

Sources
Official documentation ↗

src/backend/tcop/postgres.c — TransactionBlockStatusCode()

TransactionsSAVEPOINT

Content generated with AI assistance and reviewed for accuracy. Found an error? hello@errcodes.dev

← All PostgreSQL errors