select open change scope Open full search

PG.CENTER connects PostgreSQL documentation, reference, and ecosystem knowledge. Maintained by Pigsty.

SQLSTATE / CLASS 25 · INVALID TRANSACTION STATE

in_failed_sql_transaction

SQLSTATE
25P02
Condition name
in_failed_sql_transaction
Class
Invalid Transaction State
Source macro
ERRCODE_IN_FAILED_SQL_TRANSACTION
Evidence
Observed at runtime in the source evidence
Analysis & operational context

English SQLSTATE atlas: authored explanations and source/runtime evidence are separate from the manual definitions. View source ↗

<h1>25P02 — in_failed_sql_transaction</h1>

At a glance

25P02 is usually the second diagnostic, not the root cause. In the selected case a duplicate key first returns 23505; a following SELECT is rejected with 25P02 while the block remains INERROR. ROLLBACK is required before a valid retry.

Meaning

postgres.c checks the aborted transaction state before planning another ordinary command and reports current transaction is aborted, commands ignored until end of transaction block. A driver exposes the corresponding failed transaction status; the original error remains the diagnostic anchor, while 25P02 tells the client that ordinary work is no longer admissible in this block.

Diagnosis

Locate the first statement error before acting on 25P02, and log both diagnostics with the connection transaction status. The selected runs show root 23505, then 25P02, INERROR after each, IDLE after ROLLBACK, and a committed valid row after a new explicit BEGIN/COMMIT. Check whether a savepoint was established before the root error: ROLLBACK TO SAVEPOINT can preserve the outer transaction, whereas without one the whole failed block must end. A pool must not hand an INERROR connection to another request.

Response

Stop issuing business statements after the first error. Preserve the root SQLSTATE and details. If a deliberately established savepoint is still usable, roll back to it and continue the outer transaction; otherwise issue ROLLBACK, verify the connection is IDLE, and start a fresh transaction. Re-evaluate the operation instead of blindly replaying the root statement.

Source message

The fixed primary message is current transaction is aborted, commands ignored until end of transaction block. It describes the state left by an earlier error and does not replace the root SQLSTATE, DETAIL, or constraint identity.

Observed diagnostics

18.6 (Homebrew) / latest: root SQLSTATE 23505; secondary SQLSTATE 25P02; after root/secondary INERROR; after rollback IDLE; rows [[1, 'seed'], [2, 'repaired']]. 10.21 (Debian 10.21-1.pgdg90+1) / pg10: root SQLSTATE 23505; secondary SQLSTATE 25P02; after root/secondary INERROR; after rollback IDLE; rows [[1, 'seed'], [2, 'repaired']].

Representative case

The runner reads the root error, secondary diagnostic, rollback, and valid retry statements below from the shared registry; complete assertions, environment, and cleanup are in case export.

-- create
CREATE TABLE items(id integer PRIMARY KEY, note text UNIQUE NOT NULL);
-- seed
INSERT INTO items VALUES (1, 'seed');
-- begin
BEGIN;
-- trigger
INSERT INTO items VALUES (2, 'seed');
-- followup
SELECT 1 AS ignored;
-- rollback
ROLLBACK;
-- repair_begin
BEGIN;
-- repair
INSERT INTO items VALUES (2, 'repaired');
-- commit
COMMIT;
-- verify
SELECT id, note FROM items ORDER BY id;

The SQLSTATE, diagnostics, states, and repair assertions for this excerpt come from the shared registry (SHA-256 04da3240dcf3c03fe60d13715f8187350fadf5b8d1f10e5b837acd45289759cd); structured evidence.

Authored evidence IDs: identity, abort-state, runtime. Selected runtime records: runtime.25P02-batch2-latest-20260909.latest, runtime.25P02-batch2-pg10-20260909.pg10.

Versions and limits

The selected duplicate-key-to-25P02 case passes on PostgreSQL 18.6 and 10.21. It demonstrates transaction-state recovery, not a claim that the duplicate itself can be retried unchanged.

Sources

  • src.errcodes.18.6 (SHA-256 6e8de346643ba84aa3c9c6a73360acfc7b2dfb89162c06c08ce9bf5bcd5bbcba)
  • src.calls.REL_18_6raw/calls/REL_18_6.jsonl (SHA-256 9ee8a0e81d8f0825c5c1ae45583439859a26e602bdd4ce2f2a62aa278867ccbf)
  • src.postgres.18.6 (SHA-256 9fb62275b1badf94d01ab351337b60410cd9b3ab1fe63fa9f23d6d2185a21061)
  • doc.libpq.18.6 (SHA-256 a91ce8f29dde162245d2f35f839e8b7192f62a57e01020b80564af65edd09440) · official documentation

Source evidence

Evidence belongs to the frozen source and runtime versions listed here. It is not a runtime verification of the selected manual version.

25P02 is in_failed_sql_transaction in Class 25.

Method: Read the fixed condition row and macro.

Limits: It describes the transaction state after a prior error; it is often a secondary diagnostic.

src.errcodes.18.6

After an error aborts a transaction block, postgres.c rejects subsequent commands with 25P02 until COMMIT/ROLLBACK ends the block.

Method: Trace IsAbortedTransactionBlockState and the libpq PQTRANS_INERROR state.

Limits: The first error remains the root cause; 25P02 tells the client to stop issuing ordinary work and end the transaction.

src.postgres.18.6 src.calls.REL_18_6 doc.libpq.18.6

The selected case first raises 23505, then observes 25P02 while INERROR, rolls back to IDLE, and commits a valid row in a new explicit transaction on both targets.

Method: Read the selected summaries and structured diagnostics.

Limits: The repair demonstrates transaction-state recovery; it does not make the original duplicate valid.

runtime runtime.25P02-batch2-latest-20260909.latest runtime.25P02-batch2-pg10-20260909.pg10

Message templates

ERROR · aborted

Primary

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

The message is secondary to the earlier statement error; errdetail_abort may add context.

Reproduction & repair cases

failed_transaction_recovery · PG 10, 18

Preconditions

  • A runner-owned disposable target is provisioned.

Trigger: Raise a root unique violation, then issue a query before ROLLBACK.

Expected assertions

  • The root duplicate is 23505
  • The follow-up command reports 25P02
  • The failed transaction remains INERROR until ROLLBACK
  • A new explicit transaction commits the repaired row

Repair: Follow the explicit transaction or source boundary described by the case.

Cleanup: Drop the case schema with an owner connection.

Recorded runtime evidence

18.6 (Homebrew) · passed

Run: 25P02-batch2-latest-20260909

{
  "primary": "current transaction is aborted, commands ignored until end of transaction block",
  "sqlstate": "25P02",
  "after_25P02": "INERROR",
  "final_status": "IDLE",
  "root_primary": "duplicate key value violates unique constraint \"items_note_key\"",
  "root_sqlstate": "23505",
  "after_rollback": "IDLE",
  "after_root_error": "INERROR",
  "rows_after_retry": [
    [
      1,
      "seed"
    ],
    [
      2,
      "repaired"
    ]
  ]
}
10.21 (Debian 10.21-1.pgdg90+1) · passed

Run: 25P02-batch2-pg10-20260909

{
  "primary": "current transaction is aborted, commands ignored until end of transaction block",
  "sqlstate": "25P02",
  "after_25P02": "INERROR",
  "final_status": "IDLE",
  "root_primary": "duplicate key value violates unique constraint \"items_note_key\"",
  "root_sqlstate": "23505",
  "after_rollback": "IDLE",
  "after_root_error": "INERROR",
  "rows_after_retry": [
    [
      1,
      "seed"
    ],
    [
      2,
      "repaired"
    ]
  ]
}

Definition snapshot: english-manuals:63d7bf92a3bee9e3998d5bba5f1… · English manual source