Download

terminating connection due to idle-in-transaction timeout

Your session opened a transaction and then sat idle inside it for longer than idle_in_transaction_session_timeout, so the server closed the connection and rolled the transaction back. Find the code that leaves transactions open between statements; raise the limit only for sessions that need it.

PostgreSQL error 25P03· Tested on PostgreSQL 18.6· Updated 11 October 2026

FATAL:  terminating connection due to idle-in-transaction timeout

What it means

idle_in_transaction_session_timeout limits how long a session may sit inside an open transaction without running anything. Your session ran BEGIN (or a statement with autocommit off), did some work, and then waited longer than the limit before its next statement. The server ended the whole connection, not only the transaction, and rolled back everything the transaction had done.

You usually see it on the next statement you send, since that’s when the client notices:

FATAL:  terminating connection due to idle-in-transaction timeout
server closed the connection unexpectedly
	This probably means the server terminated abnormally
	before or while processing the request.

The setting is off (0) by default, so something set it: the server’s configuration, the role, the database, or a hosted provider. It exists because a transaction left open holds its locks and stops VACUUM from cleaning up rows changed since it began.

Two sibling limits end the connection the same way:

  • transaction_timeout (PostgreSQL 17 and later) limits a whole transaction, busy or idle: terminating connection due to transaction timeout (code 25P04).
  • idle_session_timeout (PostgreSQL 14 and later) limits idle time outside a transaction: terminating connection due to idle-session timeout (code 57P05).

Common causes

  1. Application code that begins a transaction and then waits: an HTTP call, a file upload, a message queue, or a user’s input between BEGIN and COMMIT.
  2. A missing COMMIT or ROLLBACK on an error path, so the connection goes back to the pool still inside a transaction.
  3. Autocommit turned off in a client or driver (psycopg 2 and JDBC with setAutoCommit(false), for example), so a plain SELECT opens a transaction that stays open.
  4. An interactive session where someone ran BEGIN, looked at some rows and went to lunch.

How to fix it

Find sessions that sit idle in a transaction

SELECT pid, usename, application_name, client_addr,
       now() - xact_start AS in_transaction, now() - state_change AS idle_for,
       left(query, 60) AS last_query
FROM pg_stat_activity
WHERE state = 'idle in transaction'
ORDER BY xact_start;

last_query is the last statement the session ran before going idle, which usually points at the code path.

Keep transactions short

Do the slow work (network calls, waiting for users, reading files) before BEGIN or after COMMIT. Make sure every code path ends the transaction: use your language’s with/try … finally or the framework’s transaction block rather than calling BEGIN and COMMIT by hand.

Raise or remove the limit for one role or session

If a job really needs a long-open transaction (a migration, a large export), raise the limit for it, not for everyone:

SET idle_in_transaction_session_timeout = '10min';     -- this session
ALTER ROLE reporting SET idle_in_transaction_session_timeout = 0;   -- a role

To see where the current value comes from:

SELECT setting, unit, source FROM pg_settings WHERE name = 'idle_in_transaction_session_timeout';

Let the application reconnect

The connection is gone, so the pool must discard it and open a new one. Most pools test connections before handing them out; turn that on, then retry the work.

Reproduce it

On PostgreSQL 18.6, in psql, pausing with \! sleep 3 between statements:

SET idle_in_transaction_session_timeout = '2s';
BEGIN;
UPDATE seo_err_pg.invoices SET total = total WHERE id = 1;
\! sleep 3
SELECT 1;
FATAL:  terminating connection due to idle-in-transaction timeout
server closed the connection unexpectedly
	This probably means the server terminated abnormally
	before or while processing the request.
error: connection to server was lost

With \set VERBOSITY verbose, psql shows the code: FATAL: 25P03: terminating connection due to idle-in-transaction timeout. The siblings, in new sessions with \set VERBOSITY verbose:

SET transaction_timeout = '1s';
BEGIN;
SELECT pg_sleep(2);
FATAL:  25P04: terminating connection due to transaction timeout
SET idle_session_timeout = '1s';
\! sleep 2
SELECT 1;
FATAL:  57P05: terminating connection due to idle-session timeout

Each was followed by the same server closed the connection unexpectedly lines.

In Inlet

Inlet’s Activity monitor lists the server’s sessions and the locks they hold, and can end a session (Pro), such as one left idle in a transaction that’s blocking others. Its query editor supports transactions with manual commit; commit or roll back before you leave one open, or the server’s limit will end the connection.

Inlet: a database client for the Mac

One native app for PostgreSQL, MySQL, SQL Server, SQLite, MongoDB and Redis. It explains errors where they happen, holds your edits until you save them, and keeps production read-only until you say so.

Version 0.1.0 · macOS 26 Tahoe or later · Apple silicon and Intel