$ pg_restore --list backup.dump pg_restore: error: unsupported version (1.15) in file header
Your backup is almost certainly fine. This error is not about corruption, despite reading like it is. It means the pg_restore you just ran is older than the Postgres that produced the dump.
That distinction matters more than it sounds, because the natural reaction — assuming the backup is bad — sends people off deleting archives and re-running dumps that produce the identical error.
What the number means
A custom-format dump (pg_dump -Fc) is a binary archive with a version stamped in its header. 1.15 is the archive format version, not your Postgres version.
pg_restore reads its own archive version and anything older. It cannot read anything newer, because it does not know what was added. So:
- Newer client, older archive — fine, always
- Older client, newer archive — this error
A Postgres 16 server produces archive version 1.15, which a pg_restore from Postgres 14 refuses outright.
Confirm it in ten seconds
Compare the tool you are running against the server that made the dump:
$ pg_restore --version pg_restore (PostgreSQL) 14.19 (Homebrew) $ docker exec my-postgres postgres --version postgres (PostgreSQL) 16.14
There it is. A client from 14 cannot read an archive written by 16.
This is overwhelmingly common in one specific setup: Postgres running in Docker, client tools installed on the host. The container is pinned to postgres:16, while the host has whatever apt install postgresql-client or Homebrew gave it — often several major versions behind, and drifting further every year the container stays pinned.
The fix
Use the client from inside the container
The most reliable option, because a version mismatch becomes impossible by construction. The binary that reads the archive is the same one that wrote it.
$ docker cp backup.dump my-postgres:/tmp/backup.dump $ docker exec my-postgres pg_restore --list /tmp/backup.dump 217; 1259 16394 TABLE public users app 216; 1259 16393 SEQUENCE public users_id_seq app ...
Copy the file in rather than piping it. Custom-format archives need seekable input to read their table of contents, and pg_restore --list /dev/stdin on a pipe fails for an entirely different and even more confusing reason.
Or install a matching client on the host
If you want the tools locally, take them from the PostgreSQL project's own apt repository rather than your distribution's, which is usually behind:
$ sudo apt install -y postgresql-common $ sudo /usr/share/postgresql-common/pgdg/apt.postgresql.org.sh $ sudo apt install -y postgresql-client-16
On macOS, brew install postgresql@16 and put its bin ahead of the older one on your PATH.
What not to do
Do not switch to plain SQL dumps just to dodge this. You would lose parallel restore, selective table restore, and the archive table of contents that makes custom format worth verifying in the first place. The version mismatch is a five-minute fix; the format change costs you every restore afterwards.
The part that actually matters
If your backup verification runs on the host, this error means it has been failing on every healthy backup you have ever taken.
Which leaves two bad outcomes. Either you have been ignoring the alert for months — in which case it will not tell you about the real failure when it comes — or you spent a day investigating corruption that never existed.
Related: a backup can restore perfectly and contain nothing at all — the failure this one masks.
So make it structural: always run database client tools from inside the database container. Not "when you remember", not "on the machines where the versions happen to match". A verification step that can fail for reasons unrelated to the thing being verified is not a check, it is a source of noise.