- Software and digital services
- Databases
25P02
PostgreSQL 25P02 in_failed_sql_transaction: aborted block
Evidence linked to this decision
View source: PostgreSQL 18 Appendix A: Error CodesRisk level
Medium
Proceed carefully and stop if the check is unclear.
Urgency
Medium
Quick answer
PostgreSQL returns 25P02 (in_failed_sql_transaction) because an earlier statement inside the same transaction block failed and the session has not rolled back yet. Check your logs for the first error before 25P02, then issue ROLLBACK or ROLLBACK TO a prior savepoint.
Safety first
Stop and check this first
- Never assume the SQL statement that returned 25P02 is the broken query; 25P02 only reports that the transaction block was already aborted by a prior command.
- Do not attempt to bypass transaction errors by disabling database constraints or triggers, and always issue ROLLBACK before starting a new unit of work on the same session.
Safe checks you can perform
- Locate the first SQLSTATE error that preceded 25P02 on the same session
- Check pg_stat_activity for sessions stuck in idle in transaction (aborted)
- Review transaction state handling and SAVEPOINT usage in the client code
Leave these tasks to a qualified professional
- Do not attempt this professional task: Fix the underlying SQL error and enforce ROLLBACK or ROLLBACK TO SAVEPOINT in code
- Do not attempt this professional task: Verify connection pool cleanup and libpq PQTRANS_INERROR handling
What a technician must be able to justify
Technician visit
These are the steps they must carry out and show you. Tick them as they work: if steps are skipped, do not accept a part swap.
These are not instructions for opening or handling the equipment yourself. They are the checks that should support a technical conclusion.
Fix the underlying SQL error and enforce ROLLBACK or ROLLBACK TO SAVEPOINT in code
What they doHave the developer resolve the primary SQL error that triggered the abort and update the transaction error handler so it immediately issues ROLLBACK (or ROLLBACK TO a savepoint created before the optional statement) before sending any further SQL.
They must show youthe captured first SQLSTATE before 25P02, the code diff adding ROLLBACK or SAVEPOINT / ROLLBACK TO, and integration test output.
In writingthe root-cause SQLSTATE that preceded 25P02 and the exact transaction recovery rule implemented in the service.
Verify connection pool cleanup and libpq PQTRANS_INERROR handling
What they doHave the platform engineer or DBA verify that the connection pooler and client driver inspect transaction status (PQTRANS_INERROR in libpq) and execute ROLLBACK before returning any session to the pool.
They must show youthe pooler check-in settings and a query against pg_stat_activity confirming zero lingering idle in transaction (aborted) sessions under load.
In writingthe pooler reset setting and the idle_in_transaction_session_timeout value configured on the server.
Before accepting a part or repair
Nothing has been shown yet. Do not accept a part swap based on the code alone.
Follow these steps
Note: Follow the documented order. An error code identifies the affected system, but it does not prove by itself which part has failed.
Locate the first SQLSTATE error that preceded 25P02 on the same session
- Who:
- You or your developer inspecting the application request trace or PostgreSQL server log.
- How:
- Filter the log by the backend process ID (PID), session ID, or request trace immediately before the first 25P02 entry, redacting any passwords, connection strings, or personal data before copying.
- Result that matters:
- The exact SQLSTATE code and error message of the statement that failed immediately before 25P02 began appearing.
- If an earlier statement on the same PID threw a constraint, syntax, permission, or lock error right before 25P02, that confirms the earlier statement is the true root cause to fix.
- If the very first statement of a new web request fails with 25P02 without a prior error in that request, that points to a pooled connection handed over while already in an aborted transaction block.
- Evidence to keep:
- Save the redacted log sequence showing both the initial error SQLSTATE and the subsequent 25P02 message on the same PID.
Never ignore the initial error or suppress 25P02 in logs; always redact sensitive query literals before sharing log excerpts.
Evidence: PostgreSQL 18 Appendix A: Error Codes · PostgreSQL 18 libpq connection status functions · PostgreSQL 18 transactions tutorial
Check pg_stat_activity for sessions stuck in idle in transaction (aborted)
- Who:
- Your DBA or developer with read access to pg_stat_activity.
- How:
- Run a read-only SELECT on pg_stat_activity filtering for state = 'idle in transaction (aborted)' to inspect pid, usename, application_name, xact_start, state_change, and query.
- Result that matters:
- Whether client backends are lingering in the aborted transaction state instead of rolling back promptly.
- If pg_stat_activity lists backends in state idle in transaction (aborted) for that application_name, that confirms client sessions are failing to issue ROLLBACK after query errors.
- If no backends remain in idle in transaction (aborted), that indicates the application eventually rolls back at request end after emitting one or more 25P02 errors mid-request.
- Evidence to keep:
- Record the pid, application_name, xact_start, state_change, and redacted query text from pg_stat_activity.
Do not attempt to fix aborted transactions by killing server processes at the OS level; use only read-only catalog queries during diagnosis.
Evidence: PostgreSQL ROLLBACK · PostgreSQL 18 cumulative statistics system
Review transaction state handling and SAVEPOINT usage in the client code
- Who:
- Your developer examining the data-access layer or ORM transaction block.
- How:
- Check whether the code expects to recover from an expected error inside a transaction block using SAVEPOINT and ROLLBACK TO, or whether it should abort the whole block with ROLLBACK.
- Result that matters:
- Whether every catch block inside a BEGIN ... COMMIT scope issues either ROLLBACK or ROLLBACK TO a valid savepoint defined before the failed command.
- If a catch block swallows an exception inside a transaction without calling ROLLBACK TO a prior savepoint, that confirms why PostgreSQL rejects the next query with 25P02.
- If the driver checks PQtransactionStatus and resets connections reporting PQTRANS_INERROR via ROLLBACK before reuse, that rules out pool state leakage.
- Evidence to keep:
- Keep the file and line numbers of the catch block and the connection pool reset configuration.
Evidence: PostgreSQL ROLLBACK · PostgreSQL 18 libpq connection status functions · PostgreSQL 18 transactions tutorial
Still not solved
If the error persists, stop here. See what the technician must do and show you.
Virtual technician
Does 25P02 still appear after these checks?
This guided flow uses the exact code and your answers to choose a test, an expected result and the next branch.
Where this code applies
A code is meaningful only inside the right product and version context.
Primary scope
- System
- Software and digital services
- Brand
- PostgreSQL
- Product type
- Databases
Known code variants
- in_failed_sql_transaction
- PostgreSQL 25P02
- SQLSTATE 25P02
What it means
Appendix A lists 25P02 as in_failed_sql_transaction in Class 25, Invalid Transaction State. Once any SQL command errors inside a BEGIN ... COMMIT transaction block, PostgreSQL places that transaction block into an aborted state (reported by libpq as PQTRANS_INERROR and in pg_stat_activity as idle in transaction (aborted)) and rejects further commands until the session executes ROLLBACK or rolls back to a SAVEPOINT created before the failure. Code 25P02 is a follow-on symptom of an unhandled earlier error and never proves by itself that the statement currently returning 25P02 is invalid or that the database server is damaged.
Warnings and stop conditions
- Mediumsource verified
Never assume the SQL statement that returned 25P02 is the broken query; 25P02 only reports that the transaction block was already aborted by a prior command.
Evidence: PostgreSQL 18 Appendix A: Error Codes · PostgreSQL 18 transactions tutorial
- Highsource verified
Do not attempt to bypass transaction errors by disabling database constraints or triggers, and always issue ROLLBACK before starting a new unit of work on the same session.
Evidence: PostgreSQL ROLLBACK · PostgreSQL 18 transactions tutorial
Symptoms and causes
Probable causes · in order
- Application continuing to send SQL commands after catching or ignoring an earlier errorConfirmed
When a query inside a transaction block fails and the client code catches the exception without issuing ROLLBACK or ROLLBACK TO SAVEPOINT, the next statement sent on that transaction receives 25P02.
Evidence: PostgreSQL 18 Appendix A: Error Codes · PostgreSQL ROLLBACK · PostgreSQL 18 transactions tutorial
- Client driver or ORM opening implicit transaction blocks without automatic rollbackCommon
Some client libraries and connection wrappers issue BEGIN automatically, so a single failed query leaves the session in PQTRANS_INERROR state across subsequent calls on the same connection.
Evidence: PostgreSQL 18 libpq connection status functions · PostgreSQL 18 transactions tutorial
- Connection pool returning a session left in idle in transaction (aborted) statePossible
If a pooled connection is returned to the pool after a statement error without executing ROLLBACK, the next borrower inherits the aborted transaction block and immediately hits 25P02.
Evidence: PostgreSQL ROLLBACK · PostgreSQL 18 libpq connection status functions · PostgreSQL 18 cumulative statistics system
Sources and technical references
- 1
PostgreSQL 18 Appendix A: Error Codes
PostgreSQL Global Development Group · 2026 · official_doc
- 2
PostgreSQL transaction isolation
PostgreSQL Global Development Group · 2026 · official_doc
- 3
PostgreSQL Global Development Group · 2026 · official_doc
Was this entry useful?