Skip to content
DevOps AI ToolKit
Newsletter
All guides
AI for Postgres By James Joyner IV · · 9 min read

PostgreSQL Error Guide: 'invalid page in block' Data Corruption Recovery

Fix PostgreSQL 'invalid page in block': diagnose page-level corruption, identify the affected relation, and recover with checksums and backups safely.

  • #postgres
  • #troubleshooting
  • #errors
  • #corruption

Exact Error Message

ERROR:  invalid page in block 13402 of relation base/16384/24591

With data checksums enabled, you may instead see a warning that escalates:

WARNING:  page verification failed, calculated checksum 41277 but expected 9135
ERROR:  invalid page in block 13402 of relation base/16384/24591

What the Error Means

PostgreSQL stores table and index data in fixed-size pages (8 KB by default). When it reads a page, it validates the page header and, if data checksums are enabled, the page checksum. If the header is nonsensical or the checksum does not match, PostgreSQL refuses to use the page and raises invalid page in block. This is a hard stop: the database is telling you the on-disk data for that block is not what it wrote, so it will not trust it.

The relation is identified by its file node path (base/<database_oid>/<relfilenode>), and the block number tells you exactly which 8 KB page failed. This error almost always indicates physical corruption — bad storage hardware, a failing disk, an interrupted write during a crash without proper fsync, or a filesystem/RAID problem. It can also stem from memory errors that corrupted the page before it was written. Treat it as a data-integrity incident, not a routine error.

Common Causes

  • Failing or faulty storage. Bad sectors, a dying SSD, or silent bit rot on the underlying disk corrupt the page contents.
  • Improper crash recovery. A power loss or kernel panic combined with disabled fsync, lying hardware caches, or a non-durable filesystem can leave partially written pages.
  • Memory (RAM) errors. Non-ECC memory flipping bits can corrupt a page in the buffer cache before it is flushed to disk.
  • Storage or filesystem bugs. Faulty RAID controllers, network-attached storage hiccups, or filesystem defects can return wrong data.
  • Manual file tampering. Copying or restoring data files incorrectly, or editing them outside PostgreSQL, corrupts pages.

How to Reproduce the Error

You should not deliberately corrupt a production database, but the failure surfaces naturally when a query touches the bad page. For example, a sequential scan that reaches the affected block:

SELECT count(*) FROM transactions;
-- ERROR:  invalid page in block 13402 of relation base/16384/24591

Any read path crossing block 13402 of that relation triggers it: a full scan, an index range, VACUUM, or a pg_dump. The error is deterministic for that block until the page is repaired or zeroed.

Diagnostic Commands

Map the file node from the error back to a relation name (read-only):

psql -c "SELECT relname, relkind FROM pg_class WHERE relfilenode = 24591;"

If the relfilenode does not match (it can differ from OID), resolve it via the catalog helper:

psql -c "SELECT relname FROM pg_class WHERE pg_relation_filenode(oid) = 24591;"

Confirm whether data checksums are enabled on the cluster:

psql -c "SHOW data_checksums;"

Check the server log for the surrounding checksum warnings and frequency:

sudo journalctl -u postgresql --no-pager | grep -E "invalid page|checksum" | tail -40

Inspect storage health and free space on the data directory:

df -h /var/lib/postgresql
sudo dmesg | grep -iE "I/O error|ata|nvme|sector" | tail -20

Check the cluster’s data directory location for follow-up:

psql -c "SHOW data_directory;"

Step-by-Step Resolution

  1. Take a full physical backup immediately. Before any repair attempt, copy the data directory (with the server stopped, or via your snapshot tooling). Corruption can spread; preserve the current state for recovery options.

  2. Identify the affected relation. Use the catalog queries above to translate base/16384/24591 into a table or index name. If it is an index, you are in luck — you can often REINDEX to rebuild it from the table data.

  3. Check hardware first. Review dmesg and storage SMART data. If the disk is failing, repairing the page is pointless until the hardware is replaced or the data is moved to healthy storage.

  4. Restore from backup if available. The cleanest recovery is point-in-time recovery (PITR) or restoring the affected table from a known-good logical backup. This avoids guessing about lost rows.

  5. As a last resort, isolate the bad block. If no backup exists and the table is critical, PostgreSQL offers zero_damaged_pages (a session setting) to let reads skip the corrupt page, discarding its rows. This loses data and must be done deliberately, then followed by a VACUUM and dump of the salvageable rows. Coordinate this carefully — it is destructive.

  6. Validate the rest of the database. After recovery, run VACUUM and consider pg_amcheck (or amcheck extension) to scan for additional corruption you have not hit yet.

Prevention and Best Practices

  • Initialize clusters with data checksums (initdb --data-checksums) so corruption is detected early rather than silently propagating.
  • Use ECC memory on database servers to prevent bit flips in the buffer cache.
  • Ensure storage honors fsync and disable lying write caches; verify durability after crashes.
  • Maintain tested backups and PITR (continuous WAL archiving) so any corrupted page can be recovered without guesswork.
  • Run periodic amcheck/pg_amcheck scans and monitor disk SMART health to catch failing hardware before it corrupts data.
  • For incident triage, the free incident assistant can map a corruption log block to the affected relation and a suggested recovery path.
  • could not read block ... in file ...: read only 0 of 8192 bytes — truncated or unreadable data file, a sibling corruption symptom.
  • page verification failed, calculated checksum ... but expected ... — the checksum warning that precedes this error.
  • missing chunk number ... for toast value — TOAST table corruption.
  • index ... contains unexpected zero page at block ... — index-level corruption, usually fixable with REINDEX.

Frequently Asked Questions

Is my data lost when I see this error? Not necessarily, but at least the affected 8 KB page is suspect. If you have backups or PITR, you can recover without data loss. Without backups, recovering may require zeroing the damaged page and losing the rows it held.

Can I just ignore the error and keep running? No. The error indicates physical corruption that can spread or recur. Continuing to write to failing hardware risks corrupting more pages. Investigate storage and restore from a known-good copy.

If the corrupt relation is an index, is recovery easier? Yes. Indexes are derived from table data, so a corrupt index can usually be rebuilt with REINDEX after you confirm the underlying table is healthy. Always verify the table first.

Why didn’t checksums catch this earlier? Checksums are only verified when a page is read. A page that has not been read since it was corrupted will not report an error until something touches it. They also must be enabled at initdb time (or via pg_checksums offline) to be active.

Does restarting PostgreSQL fix it? No. The corruption is on disk, not in memory, so a restart does not repair it. The same block will fail again as soon as a query reads it. Recovery requires backup restoration, reindexing, or page isolation.

Free download · 368-page PDF

Download the Free 500-Prompt DevOps AI Toolkit

500 battle-tested, copy-paste AI prompts engineered by a senior systems engineer — every one with fill-in placeholders and safety/back-out notes. Drop your email and it's yours.

  • 500 prompts: Linux · Kubernetes · Terraform · OpenStack · GitLab · Docker · Monitoring · Incident Response
  • Instant PDF download — yours free, forever
  • Plus one practical AI-workflow email a week (no spam)

Single opt-in · unsubscribe anytime · no spam.