Diagnostic Queries
Symptoms
VACUUM found a tuple whose xmin is older than the table’s relfrozenxid, which should be impossible. This indicates corruption of transaction-ID metadata, so PostgreSQL raises SQLSTATE XX001 (data_corrupted).
- A tuple’s xmin predates the relation’s frozen XID horizon.
- Surfaced during VACUUM (often autovacuum).
- Signals clog/visibility-map or heap corruption.
What the server log shows
ERROR: found xmin 1234 from before relfrozenxid 5678
Why PostgreSQL raises this — what the manual says
As Section 24.1.5 Preventing Transaction ID Wraparound Failures explains:
Once a row version is frozen its inserting XID is treated as permanently in the past, so a tuple whose xmin is reported as older than the relation’s relfrozenxid is an impossible state; PostgreSQL raises this as a data-corruption error rather than a normal vacuuming condition.
relfrozenxid is the guarantee that no live tuple has an older xmin. Finding one means the frozen-XID bookkeeping or the heap is inconsistent — corruption — and PostgreSQL reports XX001.
Common causes
- Storage corruption of heap pages or the visibility map.
- Bugs or improper recovery from a crash/backup.
- Hardware faults affecting transaction-ID metadata.
How to fix it
- Treat as serious corruption: take a backup of the current state immediately.
- Investigate hardware/storage; verify recent backups are clean.
- Restore from a known-good backup; consult upgrade notes/community for in-place repair options.
Related & next steps
Reference: PostgreSQL 18 Section 25.1.5 “Wraparound”.
Thanks — noted. This helps keep the database accurate.