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
-
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.
-
Identify the affected relation. Use the catalog queries above to translate
base/16384/24591into a table or index name. If it is an index, you are in luck — you can oftenREINDEXto rebuild it from the table data. -
Check hardware first. Review
dmesgand 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. -
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.
-
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 aVACUUMand dump of the salvageable rows. Coordinate this carefully — it is destructive. -
Validate the rest of the database. After recovery, run
VACUUMand considerpg_amcheck(oramcheckextension) 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_amcheckscans 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.
Related Errors
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 withREINDEX.
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.
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.