SQLSTATE XX001 ERROR Class XX: Internal Error

data_corrupted found xmin N from before relfrozenxid N — XX001

PostgreSQL error "found xmin N from before relfrozenxid N" (SQLSTATE XX001): what it means, common causes, and how to fix it.

PG 12, 13, 14, 15, 16, 17, 18 Official docs
Last reviewed May 2025 Grounded in source

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

  1. Treat as serious corruption: take a backup of the current state immediately.
  2. Investigate hardware/storage; verify recent backups are clean.
  3. 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”.

Was this helpful?