PG
PRO
25P02ERRORTier 1 — Safe✅ HIGH confidence

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

Category: Invalid Transaction StateVersions: All Postgres versions

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
BEGIN;
INSERT INTO users (email) VALUES (NULL); -- raises 23502 (not-null violation)

-- Transaction is now aborted; next statement triggers 25P02:
SELECT * FROM users;
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 the failed statement was not critical and the transaction should start fresh.

fix
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 partial work must be preserved and only the failed sub-operation should be rolled back.

fix
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

Why it's wrong: 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 docs: https://www.postgresql.org/docs/current/errcodes-appendix.html

📚 Feature docs: https://www.postgresql.org/docs/current/tutorial-transactions.html

🔧 Source ref: src/backend/tcop/postgres.c — TransactionBlockStatusCode()

📖 Further reading: Transactions

📖 Further reading: SAVEPOINT

Confidence assessment

✅ HIGH confidence

Stable and well-documented. The transaction state machine is fundamental to Postgres and has not changed. Edge case: in autocommit mode (outside a BEGIN block) each statement is its own transaction and 25P02 cannot occur; it only appears when using explicit transaction blocks.

See also

⚙️ This error reference was generated with AI assistance and reviewed for accuracy. Examples are provided to illustrate common scenarios and may not cover every case. Always test fixes in a development environment before applying to production. Spotted an error? Suggest a correction →