PostgreSQL WARNING: Page Verification Failed, Checksum Mismatch

SQLSTATE XX001 condition data_corrupted class XX — XX — Internal Error severity WARNING
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:

  • Standby log: WARNING: page verification failed, calculated checksum X but expected Y
  • pg_checksums was enabled on the cluster
  • Specific table or index is consistently causing the warning
  • Primary does not show the same warning for the same table
  • SMART data or filesystem errors on the standby storage

1 Environment & reproduce Free

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

? Root cause Free

  • A checksum mismatch on the standby does not necessarily mean the primary is corrupt — the standby's disk may have failed.
  • zero_damaged_pages = on allows PostgreSQL to return zero-filled pages instead of erroring — useful for reading around corrupt blocks to dump other data, but hides corruption.
  • Always verify the primary shows the same or different checksum for the same page before deciding which copy is correct.
  • Checksums detect corruption but cannot fix it — the fix is restoring from backup.
  • If checksums were enabled with pg_checksums --enable while stopped, existing pages have checksums written at enable time — subsequent corruption is detected.
  • A single corrupt page in an index: REINDEX the index. A corrupt heap page: restore from backup is the only safe option.

Verify primary does not show the same corruption. Check standby storage health. Rebuild standby from pg_basebackup. If primary is also corrupt: restore the affected table from backup.

2 Diagnose Free

RESULT
-- Check if checksums are enabled:
SELECT name, setting FROM pg_settings WHERE name = 'data_checksums';
-- OR: pg_controldata $PGDATA | grep "Data page checksum version"
-- 0 = disabled, 1 = enabled

-- On standby: check for corrupted blocks:
-- pg_filedump -i -s $PGDATA/base/oid/relfilenode | grep "checksum"

-- Check for storage errors (OS):
-- dmesg | grep -i "error\|EIO\|sector" | tail -20
-- smartctl -a /dev/sda | grep "Reallocated\|Uncorrectable"

-- Identify which table is affected:
SELECT relname, relkind, reltablespace
FROM pg_class
WHERE relfilenode = 12345;  -- use OID from the warning message

🔒 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

Verify primary does not show the same corruption. Check standby storage health. Rebuild standby from pg_basebackup. If primary is also corrupt: restore the affected table from backup.