SQLSTATE XX001 — PANIC: Could Not Write to pg_wal

SQLSTATE XX001 condition data_corrupted class XX — XX — Internal Error severity PANIC
Reproduced & verified on PostgreSQL 14.23, 15.18, 16.14, 17.10 and 18.4 — identical message on every version.
Last reviewed 28 May 2026 · Reproduced live with the SQL on this page.

! Symptoms Free

Conditions:

  • PostgreSQL log: PANIC: could not write to file "pg_wal/..." with No space left on device
  • All connections abruptly dropped
  • df -h shows 100% on the WAL partition (or data partition if they share)
  • PostgreSQL will not restart until space is freed
  • Inactive replication slots are often the cause of pg_wal growth

1 Environment & reproduce Free

Difficulty: Advanced  |  PostgreSQL versions: 12, 13, 14, 15, 16, 17

? Root cause Free

  • The only safe immediate action when pg_wal is full: free space by dropping inactive replication slots — do NOT delete files from pg_wal manually.
  • max_wal_size controls checkpoint frequency, not disk usage when replication slots hold WAL.
  • max_slot_wal_keep_size (PG13+) is the prevention: limits WAL a slot can retain before it's invalidated.
  • After freeing space, PostgreSQL recovers automatically on restart — crash recovery replays the WAL.
  • If both pg_wal and pg_base are on the same volume, temp files or table growth may also fill it.
  • Never set wal_keep_size high without also setting max_slot_wal_keep_size.

Free space by dropping inactive replication slots. Set max_slot_wal_keep_size to prevent recurrence. Restart PostgreSQL — crash recovery is automatic.

2 Diagnose Free

RESULT
-- BEFORE restart (investigate cause):
-- df -h $PGDATA                            ← is disk actually full?
-- du -sh $PGDATA/pg_wal/                   ← WAL directory size
-- ls $PGDATA/pg_wal/*.history              ← timeline files
-- du -sh $PGDATA/pg_wal/*.* | sort -h | tail -20

-- Check replication slots (common culprit):
SELECT slot_name, active, wal_status,
    pg_size_pretty(pg_wal_lsn_diff(pg_current_wal_lsn(), confirmed_flushed_lsn))
        AS retained_wal
FROM pg_replication_slots
ORDER BY confirmed_flushed_lsn;
-- inactive slots with large retained_wal = cause of disk full

🔒 Diagnose deeper Pro

🔒

Find every latent occurrence before it ships

The steps above clear this incident. Pro adds the executed, verified depth that stops the whole class of bug across your fleet.

  • Catalog & log queries that surface every at-risk object before a migration ships.
  • Inspect-without-running tricks (\gdesc and friends).
  • Exactly where the log line surfaces on RDS, Azure & Cloud SQL.
  • Cross-version gotchas, verified on PostgreSQL 14–18.
Unlock Pro from $24.99/mo · or $199/yr — unlocks every Pro section.

Every Pro query on this site is executed against real PostgreSQL and verified — we never publish an untested snippet.

3 Recovery & verify Free

Free space by dropping inactive replication slots. Set max_slot_wal_keep_size to prevent recurrence. Restart PostgreSQL — crash recovery is automatic.