PostgreSQL terminates idle transactions to prevent locks and table bloat. Configure idle_in_transaction_session_timeout to set a maximum idle period, or disable it (0ms) for maintenance operations.
This error occurs when a PostgreSQL session remains idle within an open transaction for longer than the configured idle_in_transaction_session_timeout value. PostgreSQL automatically terminates such sessions to reclaim resources. Idle transactions can hold locks that block other queries and prevent VACUUM from cleaning up dead rows, causing table bloat and index growth. The error message is: "ERROR: terminating connection due to idle-in-transaction timeout".
Connect to PostgreSQL and query the current value:
SHOW idle_in_transaction_session_timeout;A value of 0 means the timeout is disabled. Values are specified in milliseconds (e.g., 5000 = 5 seconds, 300000 = 5 minutes).
Set a timeout value appropriate for your application. Set it at the database, role, or session level:
Session level (temporary, current session only):
SET idle_in_transaction_session_timeout = '10min';Role level (persistent for specific users):
ALTER ROLE your_app_user SET idle_in_transaction_session_timeout = '10min';Database level (persistent for all users of this database):
ALTER DATABASE your_database SET idle_in_transaction_session_timeout = '5min';System-wide (in postgresql.conf):
idle_in_transaction_session_timeout = '5min'Then reload configuration:
SELECT pg_reload_conf();The best practice is to prevent idle transactions in the first place:
Commit transactions promptly:
// BAD: Opens transaction, then waits
const result = await db.transaction(async (trx) => {
await trx.insert({...});
// Application waits for user input here - transaction is idle
const userInput = await waitForUserInput();
return trx.update({...});
});
// GOOD: Minimize transaction scope
const userInput = await waitForUserInput();
const result = await db.transaction(async (trx) => {
await trx.insert({...});
return trx.update({...});
});Use connection pooling properly:
// Ensure connections are returned promptly
await client.query('BEGIN');
try {
await doWork();
await client.query('COMMIT');
} catch (e) {
await client.query('ROLLBACK');
} finally {
client.release(); // Important: release connection
}For long-running operations like pg_dump, backups, or index rebuilds, temporarily disable the timeout:
# Increase timeout for pg_dump
pg_dump --command="SET idle_in_transaction_session_timeout = 0" your_database > backup.sqlOr within a transaction:
SET idle_in_transaction_session_timeout = 0; -- Disable
CREATE INDEX CONCURRENTLY idx_large ON huge_table(column);
RESET idle_in_transaction_session_timeout; -- Re-enableFind long-running idle transactions:
SELECT pid, usename, application_name, state, state_change
FROM pg_stat_activity
WHERE state = 'idle in transaction'
ORDER BY state_change ASC;Check which queries are holding locks:
SELECT
l.locktype, l.database, l.relation, l.page, l.tuple,
a.usename, a.application_name, a.pid
FROM pg_locks l
JOIN pg_stat_activity a ON l.pid = a.pid
WHERE NOT l.granted;The idle_in_transaction_session_timeout was introduced in PostgreSQL 9.6. Related timeout parameters: idle_session_timeout (applies to all idle sessions, not just those in transactions) and statement_timeout (limits execution time of individual queries, not idle time). Long-running statements are NOT affected by this timeout—only idle periods within transactions. When combined with connection pooling (PgBouncer, Pgpool-II), ensure pooler timeouts are configured separately and don't conflict with server timeouts. Some hosting providers (AWS RDS, Heroku) may enable this by default; check your provider's documentation.
ERROR: syntax error at end of input
Syntax error at end of input in PostgreSQL
Bind message supplies N parameters but prepared statement requires M
Bind message supplies N parameters but prepared statement requires M in PostgreSQL
Multidimensional arrays must have sub-arrays with matching dimensions
Multidimensional arrays must have sub-arrays with matching dimensions
ERROR: value too long for type character varying
Value too long for type character varying
insufficient columns in unique constraint for partition key
How to fix "insufficient columns in unique constraint for partition key" in PostgreSQL