SQLSTATE XX000 — internal_error: Database Files Moved to Different System
! Symptoms Free
Conditions:
- PostgreSQL fails to start with
FATAL: database files are incompatible with server postmaster.pidfile exists in PGDATA (copied while server was running)pg_controldatashowsDatabase cluster state: in production(not shut down)pg_wal/directory missing or incomplete WAL files- Version mismatch between binaries and data directory
1 Environment & reproduce Free
Difficulty: Advanced | PostgreSQL versions: 12, 13, 14, 15, 16, 17
? Root cause Free
- Copying a live PGDATA with
rsyncis never safe — files change during copy, producing an inconsistent snapshot. Always usepg_basebackupfor live copies. - Deleting
postmaster.pidis safe on the new server only — confirms no PostgreSQL process owns the directory. pg_controldatashowsin production→ PostgreSQL will attempt crash recovery on start (usually succeeds if WAL is intact).- If WAL files are missing: start fails with
PANIC: could not locate a valid checkpoint record. Need a WAL archive or a proper backup. - Different PostgreSQL major versions = binaries incompatible with data directory. Use
pg_upgradefor major version migration. - File ownership/permissions must match the postgres OS user on the new server.
Delete postmaster.pid on new server. Touch recovery.signal to force recovery mode. Start PostgreSQL — it will attempt crash recovery. If WAL is intact, it succeeds. If WAL missing, restore from a clean pg_basebackup.
2 Diagnose Free
RESULT-- Check pg_control state (run as OS command): -- pg_controldata $PGDATA | grep "Database cluster state" -- "in production" = was not shut down cleanly before copy -- "shut down" = safe to start -- Check version compatibility: -- cat $PGDATA/PG_VERSION -- postgres --version -- Check for postmaster.pid: -- ls -la $PGDATA/postmaster.pid -- If exists: delete ONLY if certain no PostgreSQL is running on this host -- After starting (with recovery.signal): -- psql -c "SELECT pg_is_in_recovery();"
🔒 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 (
\gdescand friends). - ✓Exactly where the log line surfaces on RDS, Azure & Cloud SQL.
- ✓Cross-version gotchas, verified on PostgreSQL 14–18.
Every Pro query on this site is executed against real PostgreSQL and verified — we never publish an untested snippet.
Already a member? Log in
3 Recovery & verify Free
Delete postmaster.pid on new server. Touch recovery.signal to force recovery mode. Start PostgreSQL — it will attempt crash recovery. If WAL is intact, it succeeds. If WAL missing, restore from a clean pg_basebackup.