How to fix pg_dump: error: query failed: server closed the connection in PostgreSQL

PostgreSQLINTERMEDIATEMEDIUMUpdated May 28, 2026· 162 views

This error occurs when PostgreSQL terminates the pg_dump connection mid-backup. Common causes are idle/statement timeouts, parallel-worker idling, and firewalls dropping idle TCP connections. Check server logs and adjust timeouts.

Quick fix

Fixes pg_dump: error: query failed: server closed the connection

# Linux/macOS
sudo tail -f /var/log/postgresql/postgresql.log

# Or query from psql (if accessible)
SELECT pg_current_logfile();
SELECT * FROM pg_read_file('/path/to/log/file');
  1. Check PostgreSQL server logs for detailed error information
  2. Disable idle_in_transaction_session_timeout for the backup user
  3. Disable or increase statement_timeout for pg_dump
  4. Use pg_dump with --lock-wait-timeout to prevent extended locks
postgresql — error
# Linux/macOS
sudo tail -f /var/log/postgresql/postgresql.log
# Or query from psql (if accessible)
SELECT pg_current_logfile();
SELECT * FROM pg_read_file('/path/to/log/file');
pg_dump: error: query failed: server closed the connection

What this error means

The pg_dump utility opens a connection to PostgreSQL and executes queries to read the database schema and data. The "server closed the connection" error means PostgreSQL abruptly terminated that connection before pg_dump finished reading the backup data. This can happen mid-dump or at specific points depending on the underlying cause. The error is usually preceded by server-side events like timeout expiration, insufficient resources, or explicit connection termination. Unlike permanent schema/data corruption, this is a connectivity or resource issue that often resolves once the root cause is addressed.

Typical symptoms

  • pg_dump stops abruptly with 'server closed the connection' message
  • Dumps of large databases fail partway through
  • Error occurs at unpredictable points in the backup process
  • Parallel pg_dump (with -j flag) fails more frequently than sequential dumps
  • Scheduled backup jobs fail intermittently but sometimes succeed
  • PostgreSQL logs show connection resets or idle timeout messages
  • Dumps complete successfully from localhost but fail from remote machines

Common causes

  1. idle_in_transaction_session_timeout parameter is too short and terminates idle backup sessions
  2. statement_timeout parameter expires during long-running table dumps
  3. Firewall or network gateway closes idle TCP connections after prolonged inactivity
  4. Parallel pg_dump workers remain idle in transaction while waiting for locks, triggering timeout
  5. PostgreSQL server crashes or is restarted during the backup process
  6. Insufficient server resources (memory, file descriptors) force connection termination
  7. SSL renegotiation errors on encrypted connections
  8. Network connectivity issues between pg_dump client and PostgreSQL server

How to fix "pg_dump: error: query failed: server closed the connection"

1Check PostgreSQL server logs for detailed error information

Examine the PostgreSQL server logs to understand why the connection was closed. The server logs are typically located at:

bash
# Linux/macOS
sudo tail -f /var/log/postgresql/postgresql.log

# Or query from psql (if accessible)
SELECT pg_current_logfile();
SELECT * FROM pg_read_file('/path/to/log/file');

Look for messages like:
- "terminating connection due to idle-in-transaction timeout"
- "canceling statement due to statement timeout"
- "could not send data to client: Connection reset by peer"
- "could not send data to client: Connection timed out"
- "terminating connection due to administrator command"

These messages indicate which limit was exceeded.

2Disable idle_in_transaction_session_timeout for the backup user

If server logs show 'idle-in-transaction timeout', the idle_in_transaction_session_timeout parameter is terminating idle backup sessions. This commonly happens with parallel pg_dump (-j flag) when worker sessions wait idle while another worker is processing a large table.

Disable the timeout for the backup user:

sql
-- Option 1: Disable for specific user (most secure)
ALTER USER backup_user SET idle_in_transaction_session_timeout = '0';

-- Option 2: Disable at database level
ALTER DATABASE your_database SET idle_in_transaction_session_timeout = '0';

-- Verify the setting
SHOW idle_in_transaction_session_timeout;

Or set it temporarily via environment variable when running pg_dump:

bash
PGOPTIONS="-c idle_in_transaction_session_timeout=0" pg_dump -h localhost -U backup_user -d your_database > backup.sql
3Disable or increase statement_timeout for pg_dump

If the server logs show 'canceling statement due to statement timeout', adjust the statement_timeout parameter:

sql
-- Option 1: Disable statement timeout for the backup user
ALTER USER backup_user SET statement_timeout = '0';

-- Option 2: Disable at database level
ALTER DATABASE your_database SET statement_timeout = '0';

-- Option 3: Increase to a large value (e.g., 1 hour)
ALTER USER backup_user SET statement_timeout = '3600000';

Or set it via environment variable:

bash
PGOPTIONS="-c statement_timeout=0" pg_dump -h localhost -U backup_user -d your_database > backup.sql

Note: statement_timeout = '0' disables the timeout entirely, suitable for administrative tasks like backups.

4Use pg_dump with --lock-wait-timeout to prevent extended locks

The --lock-wait-timeout option tells pg_dump to fail fast if it cannot acquire table locks, rather than waiting indefinitely:

bash
pg_dump -h localhost -U backup_user -d your_database --lock-wait-timeout=10s > backup.sql

This is helpful if pg_dump is being blocked by long-running transactions. Acceptable formats for the timeout are:
- "10s" (seconds)
- "1min" (minute)
- "2min" (minutes)

If pg_dump still fails due to locks, you may need to identify and terminate blocking queries:

sql
SELECT pid, usename, query, state FROM pg_stat_activity WHERE state != 'idle';
SELECT pg_terminate_backend(pid) FROM pg_stat_activity WHERE query ILIKE '%some_long_query%';
5Switch from parallel to sequential pg_dump if timeouts persist

Parallel pg_dump (using -j flag) opens multiple worker connections that may idle while waiting for table locks. If you're seeing timeout errors with parallel dumps, try sequential mode:

bash
# Parallel dump (more prone to timeouts) - requires directory format
pg_dump -h localhost -U backup_user -d your_database -j 4 -F d -f ./backup_dir

# Sequential dump (less prone to timeouts)
pg_dump -h localhost -U backup_user -d your_database > backup.sql

Note: parallel dumps (-j) require the directory format (-F d) and cannot be written to a plain SQL file or stdout. Sequential dumps are slower but more reliable on systems with aggressive timeout settings. For very large databases, consider:
- Using pg_dump --format=custom which produces a compact, restorable archive
- Dumping individual schemas or tables instead of the entire database
- Scheduling dumps during low-activity periods to reduce lock contention

6Check network connectivity and enable TCP keepalives

If server logs show 'could not send data to client: Connection reset by peer' or 'Connection timed out', the issue is network-related:

bash
# Test TCP connectivity to PostgreSQL
nc -zv localhost 5432

# If dumping from a remote machine, verify hostname/port reachability
ping <postgres_host>
nc -zv <postgres_host> 5432

Network issues to investigate:
- Firewall drops idle connections after a timeout period (common in cloud environments)
- Network switch or gateway has aggressive connection timeout
- NAT router resets long-lived connections
- Corporate proxy drops idle TCP streams

To keep idle connections alive across firewalls/NAT, enable libpq TCP keepalives in the connection string (there is no --no-reconnect option in pg_dump). Pass keepalive parameters through -d as a connection URI or keyword string:

bash
# Connection URI form
pg_dump -d "postgresql://backup_user@db_host:5432/your_database?keepalives=1&keepalives_idle=30&keepalives_interval=10&keepalives_count=5" -v > backup.sql

# Keyword/value form
pg_dump -d "host=db_host user=backup_user dbname=your_database keepalives=1 keepalives_idle=30 keepalives_interval=10 keepalives_count=5" -v > backup.sql

These settings make the OS send TCP keepalive probes every 30 seconds while idle, preventing stateful firewalls and NAT devices from silently dropping the connection during long backups.

7Verify PostgreSQL server is not running out of resources

Resource exhaustion (memory, file descriptors, connections) can force connection termination. Check server health:

bash
# Check available memory and file descriptors
free -h
ulimit -n

# On Linux, check PostgreSQL process resource limits
cat /proc/$(pidof postgres)/limits

# Check current connection count
psql -c "SELECT count(*) as connections FROM pg_stat_activity;"
psql -c "SHOW max_connections;"

If nearing connection limits:

sql
-- Increase max_connections (postmaster-level parameter: requires a full PostgreSQL RESTART, not just a reload)
ALTER SYSTEM SET max_connections = 500;
-- Then restart the PostgreSQL service for the change to take effect

-- Or use a connection pooler like PgBouncer to reduce backend connections

For memory issues, check if PostgreSQL is swapping. Use swapon to inspect swap usage (note: swapoff disables swap and is not a status command):

bash
ps aux | grep postgres
free -h
swapon --show   # or: swapon -s
8Enable pg_dump verbose mode to identify where it fails

Use -v (verbose) or -vv (extra verbose) to see exactly which table is being dumped when the error occurs:

bash
pg_dump -h localhost -U backup_user -d your_database -vv > backup.sql 2>dump.log
cat dump.log

Verbose output shows:
- "dumping contents of table TABLE_NAME"
- The exact point where the connection was lost

If a specific table consistently causes the error, that table may be:
- Very large (exceeds statement_timeout)
- Locked by another process
- Corrupted (uncommon but possible)

You can dump that problematic table separately or exclude it:

bash
# Dump all except problematic_table
pg_dump -h localhost -U backup_user -d your_database -T problematic_table > backup.sql

# Dump only a specific table
pg_dump -h localhost -U backup_user -d your_database -t specific_table > table.sql
9Test with custom format dump as an alternative

The plain SQL text format (-F p, default) streams output as raw SQL text. Try the custom archive format, which is more compact and supports compression and selective restore:

bash
# Plain text format (default)
pg_dump -h localhost -U backup_user -d your_database -F p > backup.sql

# Custom format (compressed archive, supports selective restore)
pg_dump -h localhost -U backup_user -d your_database -F c > backup.custom

# Directory format (allows parallel dump and restore)
pg_dump -h localhost -U backup_user -d your_database -F d -f ./backup_dir

Custom format benefits:
- Compressed by default (control with -Z), reducing the data written
- Supports selective restore of individual objects
- Works with pg_restore parallelism (-j)

Restore custom format dumps:

bash
pg_restore -d target_database backup.custom

Note: the format itself does not change PostgreSQL's timeout behavior; if timeouts are the root cause, combine this with the timeout fixes in the earlier steps.

Advanced notes

Parallel pg_dump and Idle Transactions: Parallel pg_dump uses multiple worker connections coordinated by a supervisor process. While one worker dumps a large table, others can remain idle in transaction. If idle_in_transaction_session_timeout is set (common for production safety), these idle workers may be terminated, breaking the backup. Set idle_in_transaction_session_timeout to 0 for the backup user. SSL Renegotiation Issues: Very old PostgreSQL versions (pre-9.5) with certain SSL libraries renegotiated SSL keys during long operations; SSL renegotiation was removed in PostgreSQL 9.5+, so this only affects legacy servers. If logs show SSL errors on such a server, the durable fix is to upgrade PostgreSQL. TCP Keepalives: For backups that cross firewalls or NAT, libpq keepalive parameters (keepalives, keepalives_idle, keepalives_interval, keepalives_count) in the connection string keep idle connections from being dropped; this is the supported mechanism (pg_dump has no --no-reconnect flag). Connection Poolers: If using PgBouncer or Pgpool, verify the pooler does not have aggressive idle timeouts, and prefer session pooling (or route backups directly to PostgreSQL, bypassing the pooler) so pg_dump's transaction-scoped work is not disrupted. Remote Backups: Network timeouts are more common on remote backups across the internet. Running pg_dump on (or near) the database host and streaming the resulting file over SSH reduces the time the database connection stays open: pg_dump -F c your_database | ssh remote_server 'cat > backup.custom'. Monitoring for Patterns: Log failed backups with timestamps and compare against pg_stat_statements or slow-query logs to identify correlations with high database load, specific tables, or time of day.

Frequently asked questions

What does "pg_dump: error: query failed: server closed the connection" mean?
The pg_dump utility opens a connection to PostgreSQL and executes queries to read the database schema and data. The "server closed the connection" error means PostgreSQL abruptly terminated that connection before pg_dump finished reading the backup data. This can happen mid-dump or at specific points depending on the underlying cause.
How do I fix "pg_dump: error: query failed: server closed the connection"?
This error occurs when PostgreSQL terminates the pg_dump connection mid-backup. Common causes are idle/statement timeouts, parallel-worker idling, and firewalls dropping idle TCP connections. Check server logs and adjust timeouts.
What causes "pg_dump: error: query failed: server closed the connection"?
idle_in_transaction_session_timeout parameter is too short and terminates idle backup sessions statement_timeout parameter expires during long-running table dumps Firewall or network gateway closes idle TCP connections after prolonged inactivity
Is the "pg_dump: error: query failed: server closed the connection" error serious?
It is a medium-severity error — more of a blocker than a risk. The steps above resolve it.

Official resources & further reading