pg_resetwal: refuse to run when backup_label exists

Started by shihao zhong24 days ago14 messageshackers
Beta feature

Hackorum builds and tests every patch posted to the lists, not only commitfest submissions. This is Hackorum's own CI rather than the PostgreSQL project's, and it is still under testing - please report anything that looks wrong.

appliessuccessCI history

You can run a PostgreSQL built from this patch straight from Docker, with no checkout and no build:

docker run --rm -p 5432:5432 ghcr.io/hackorum-dev/postgres-patch:t253985
psql -h localhost -U postgres

Built from patchset v6 (message #6), October 22, 2026 at 10:41 AM.

Every patchset is also pushed to a branch of our PostgreSQL fork, so you can check out the same tree CI built. Without a PostgreSQL checkout:

git clone --branch t253985_6 https://github.com/hackorum-dev/postgres.git

In a checkout you already have, add the fork once:

git remote add hackorum https://github.com/hackorum-dev/postgres.git

then, for this patchset and every later one:

git fetch hackorum t253985_6 && git checkout t253985_6

Patchset v6 (message #6) is on t253985_6

Jump to latest
#1shihao zhong
zhong950419@gmail.com

Hi hackers,

pg_resetwal does not look for backup_label today. On a restored base
backup, pg_control says "in production", so pg_resetwal asks for -f, and
with -f it goes ahead. The server then fails with "could not locate
required checkpoint record" and a hint to remove backup_label. Removing it
at that point throws away what the backup needs to become consistent.

The attached patch makes pg_resetwal refuse when backup_label exists, even
with -f. This follows the postmaster.pid check, which -f does not override
either. It came up in the CF 4997 thread [1]/messages/by-id/e2636c5d-c031-43c9-a5d6-5e5c7e4c5514@pgmasters.net, and David preferred that -f
not bypass it [2]/messages/by-id/556bef11-938d-45ca-94b3-7143a3cb532d@pgbackrest.org. On a pg_basebackup copy it now says:

pg_resetwal: error: backup label file "backup_label" exists
pg_resetwal: hint: If you are restoring from a backup, configure recovery
instead. If you are not restoring from a backup, delete the backup label
file and try again.

-n is refused too. A dry run should show what a real run would do, and the
real run refuses. pg_controldata still works for reading the control file.

Robert worried in [3]/messages/by-id/CA+TgmoZkdrWyd7KiPFHaJBg+tjM3UFrqOBK1EtG3NtVs97-7Xw@mail.gmail.com that people with a bad backup will just run
pg_resetwal, which is worse than starting from the wrong checkpoint. This
patch targets that step. A backup that still has its backup_label is the
case where the user has everything needed for a correct restore, and
pg_resetwal is the wrong tool. Now it says so before it does any damage. A
user can still delete the file and rerun, but that is a second deliberate
step, and the docs now say when that is safe.

0002 adds TAP tests and is optional. I think this is master only, since it
changes what an existing command accepts.

[1]: /messages/by-id/e2636c5d-c031-43c9-a5d6-5e5c7e4c5514@pgmasters.net
[2]: /messages/by-id/556bef11-938d-45ca-94b3-7143a3cb532d@pgbackrest.org
[3]: /messages/by-id/CA+TgmoZkdrWyd7KiPFHaJBg+tjM3UFrqOBK1EtG3NtVs97-7Xw@mail.gmail.com
/messages/by-id/CA+TgmoZkdrWyd7KiPFHaJBg+tjM3UFrqOBK1EtG3NtVs97-7Xw@mail.gmail.com

Thanks,
Shihao

Attachments:

t253985_1
v1-0002-Test-pg_resetwal-backup_label-check.patchapplication/octet-stream; name=v1-0002-Test-pg_resetwal-backup_label-check.patchDownload+23-1
v1-0001-pg_resetwal-Refuse-to-run-when-backup_label-exist.patchapplication/octet-stream; name=v1-0001-pg_resetwal-Refuse-to-run-when-backup_label-exist.patchDownload+32-2
#2Michael Paquier
michael@paquier.xyz
In reply to: shihao zhong (#1)
Re: pg_resetwal: refuse to run when backup_label exists

On Mon, Sep 28, 2026 at 11:02:00PM -0700, shihao zhong wrote:

Robert worried in [3] that people with a bad backup will just run
pg_resetwal, which is worse than starting from the wrong checkpoint. This
patch targets that step. A backup that still has its backup_label is the
case where the user has everything needed for a correct restore, and
pg_resetwal is the wrong tool. Now it says so before it does any damage. A
user can still delete the file and rerun, but that is a second deliberate
step, and the docs now say when that is safe.

0002 adds TAP tests and is optional. I think this is master only, since it
changes what an existing command accepts.

FWIW, I don't think that we should restrict that at all. pg_resetwal
is a footgun if one does not know what he/she is doing. However, if
one knows his business, even using pg_resetwal on a data folder with a
backup_label file around can prove incredibly useful when salvaging
data from a corrupted instance.

One thing that may be interesting to me is something much different
than what you are sending: an option to overwrite DBState in
ControlFileData to something else than DB_SHUTDOWNED. Hence that
would be the opposite of a restriction.

Note: pg_resetwal should have been renamed a long time ago. Perhaps
it should just be pg_control_update or something like that. I am
pretty sure that pg_footgun has been mentioned to me once, at some
point. Jokes apart, *that* naming could be a serious option to make
people aware that this a tool you should not use if you do not
absolutely know what you are doing.
--
Michael

#3shihao zhong
zhong950419@gmail.com
In reply to: Michael Paquier (#2)
Re: pg_resetwal: refuse to run when backup_label exists

Hi Michael,

However, if
one knows his business, even using pg_resetwal on a data folder with a
backup_label file around can prove incredibly useful when salvaging
data from a corrupted instance.

That still works with the patch. The only change is that backup_label
has to be removed before pg_resetwal and not after. Today it has to go
anyway. After pg_resetwal -f the server stops with "could not locate
required checkpoint record" until the file is removed. Both orders give
the same data directory on master, pg_control and the new WAL segment
included.

Does that change your view? If not, I can let -f override the check.
Then the patch is only a clearer error without -f, plus the doc
paragraph.

One thing that may be interesting to me is something much different
than what you are sending: an option to overwrite DBState in
ControlFileData to something else than DB_SHUTDOWNED.

0003 in the attached v2 is a first try for that. It adds
--cluster-state, which takes shut-down, shut-down-in-recovery,
shutting-down, in-crash-recovery, in-archive-recovery or in-production.
DB_STARTUP is left out because the server refuses to start with it.

With any value other than shut-down, the next start goes through crash
recovery. One visible effect is that unlogged tables are emptied. Today
they keep what was on disk after a crash and pg_resetwal -f.

Thanks,
Shihao

Attachments:

t253985_3
v2-0001-pg_resetwal-Refuse-to-run-when-backup_label-exist.patchapplication/octet-stream; name=v2-0001-pg_resetwal-Refuse-to-run-when-backup_label-exist.patchDownload+32-2
v2-0003-pg_resetwal-Add-cluster-state-option.patchapplication/octet-stream; name=v2-0003-pg_resetwal-Add-cluster-state-option.patchDownload+61-2
v2-0004-Test-pg_resetwal-cluster-state.patchapplication/octet-stream; name=v2-0004-Test-pg_resetwal-cluster-state.patchDownload+22-1
v2-0002-Test-pg_resetwal-backup_label-check.patchapplication/octet-stream; name=v2-0002-Test-pg_resetwal-backup_label-check.patchDownload+23-1
#4David Steele
david@pgbackrest.org
In reply to: shihao zhong (#3)
Re: pg_resetwal: refuse to run when backup_label exists

On 10/2/26 07:43, shihao zhong wrote:

Hi Michael,

However, if
one knows his business, even using pg_resetwal on a data folder with a
backup_label file around can prove incredibly useful when salvaging
data from a corrupted instance.

That still works with the patch. The only change is that backup_label
has to be removed before pg_resetwal and not after. Today it has to go
anyway. After pg_resetwal -f the server stops with "could not locate
required checkpoint record" until the file is removed. Both orders give
the same data directory on master, pg_control and the new WAL segment
included.

Does that change your view? If not, I can let -f override the check.
Then the patch is only a clearer error without -f, plus the doc
paragraph.

Given that the server will not start after pg_resetwal until
backup_label is removed I think it makes sense to force the user to
remove it beforehand. I'd prefer they remove it manually but I suppose
we could have -f remove it. Either way, it seems like pg_resetwal should
leave the cluster in a state where it can be started.

One thing that may be interesting to me is something much different
than what you are sending: an option to overwrite DBState in
ControlFileData to something else than DB_SHUTDOWNED.

0003 in the attached v2 is a first try for that. It adds
--cluster-state, which takes shut-down, shut-down-in-recovery,
shutting-down, in-crash-recovery, in-archive-recovery or in-production.
DB_STARTUP is left out because the server refuses to start with it.

With any value other than shut-down, the next start goes through crash
recovery. One visible effect is that unlogged tables are emptied. Today
they keep what was on disk after a crash and pg_resetwal -f.

I'd say this should be the subject of a separate patch and thread. I'm
honestly not sure how useful it would be aside from test scenarios.

Regards,
-David

#5Joao Detomini
joao.detomini@enterprisedb.com
In reply to: David Steele (#4)
Re: pg_resetwal: refuse to run when backup_label exists

Hi Shihao,

I applied v2-0001 and v2-0002 on current master and ran the
pg_resetwal tests, plus the recovery and pg_basebackup suites since
pg_createsubscriber also runs pg_resetwal; no failures. I also tried
it by hand on a pg_basebackup copy: both "pg_resetwal -f" and
"pg_resetwal -n" now refuse with the new error and hint.

I checked the claim about the order of operations as well. On
unpatched master, "pg_resetwal -f" on a backup makes the server fail
to start ("could not locate required checkpoint record"), and the
server's own hint says that removing backup_label leaves a corrupt
cluster. I then took two copies of the same backup, one with
pg_resetwal first and backup_label removed afterwards, the other the
other way round. The pg_controldata output and the pg_wal file names
are the same, except for the timestamps.

Given that, I'd keep the check as it is, without letting -f override
it. The server won't start until backup_label is gone anyway, so
asking for the removal first doesn't take anything away from the
salvage case Michael described, it only makes the user do it on
purpose. Today the warning about backup_label only shows up after
pg_resetwal has already run, and with -f nothing warns at all.

Two small things. The Discussion: trailer points at David's message
in the CF 4997 thread; I guess it should point at this thread. And a
restored backup normally has tablespace_map too, while the check only
looks at backup_label; is ignoring it on purpose?

Thanks,
João Marcelo

Em sex., 2 de out. de 2026 às 07:25, David Steele <david@pgbackrest.org>
escreveu:

Show quoted text

On 10/2/26 07:43, shihao zhong wrote:

Hi Michael,

However, if
one knows his business, even using pg_resetwal on a data folder with a
backup_label file around can prove incredibly useful when salvaging
data from a corrupted instance.

That still works with the patch. The only change is that backup_label
has to be removed before pg_resetwal and not after. Today it has to go
anyway. After pg_resetwal -f the server stops with "could not locate
required checkpoint record" until the file is removed. Both orders give
the same data directory on master, pg_control and the new WAL segment
included.

Does that change your view? If not, I can let -f override the check.
Then the patch is only a clearer error without -f, plus the doc
paragraph.

Given that the server will not start after pg_resetwal until
backup_label is removed I think it makes sense to force the user to
remove it beforehand. I'd prefer they remove it manually but I suppose
we could have -f remove it. Either way, it seems like pg_resetwal should
leave the cluster in a state where it can be started.

One thing that may be interesting to me is something much different
than what you are sending: an option to overwrite DBState in
ControlFileData to something else than DB_SHUTDOWNED.

0003 in the attached v2 is a first try for that. It adds
--cluster-state, which takes shut-down, shut-down-in-recovery,
shutting-down, in-crash-recovery, in-archive-recovery or in-production.
DB_STARTUP is left out because the server refuses to start with it.

With any value other than shut-down, the next start goes through crash
recovery. One visible effect is that unlogged tables are emptied. Today
they keep what was on disk after a crash and pg_resetwal -f.

I'd say this should be the subject of a separate patch and thread. I'm
honestly not sure how useful it would be aside from test scenarios.

Regards,
-David

#6shihao zhong
zhong950419@gmail.com
In reply to: Joao Detomini (#5)
Re: pg_resetwal: refuse to run when backup_label exists

Hi Joao,

T hanks for testing it, and for checking the order of operations.

The Discussion: trailer points at David's message
in the CF 4997 thread; I guess it should point at this thread.

The patch came out of that thread. That message is where David said
-f should not override the check. v3 keeps it and adds this thread as
a second Discussion line.

And a
restored backup normally has tablespace_map too, while the check only
looks at backup_label; is ignoring it on purpose?

Yes. The server reads tablespace_map only when backup_label is there.
Without backup_label it renames the file to tablespace_map.old and
starts as usual. So tablespace_map alone does not stop the server from
starting, and there is nothing for pg_resetwal to guard against.
v3 also leaves out the --cluster-state patches, as David suggested.
0001 and 0002 have no code changes.

Thanks,
Shihao

Attachments:

t253985_6
v3-0002-Test-pg_resetwal-backup_label-check.patchapplication/octet-stream; name=v3-0002-Test-pg_resetwal-backup_label-check.patchDownload+23-1
v3-0001-pg_resetwal-Refuse-to-run-when-backup_label-exist.patchapplication/octet-stream; name=v3-0001-pg_resetwal-Refuse-to-run-when-backup_label-exist.patchDownload+32-2
#7Joao Detomini
joao.detomini@enterprisedb.com
In reply to: shihao zhong (#6)
Re: pg_resetwal: refuse to run when backup_label exists

Hi Shihao,

Thanks for v3. I applied it on current master and the pg_resetwal
tests pass.

On -f: pg_resetwal only lets it override uncertainty about the state
of pg_control, not known facts about the directory. postmaster.pid is
the closest case. -f doesn't bypass it and the user has to delete the
file by hand, even though a stale one after a crash is normal. A
backup_label looks like that second kind to me, so I'd keep v3 as is.

Thanks,
João Marcelo

Em seg., 5 de out. de 2026 às 00:47, shihao zhong <zhong950419@gmail.com>
escreveu:

Show quoted text

Hi Joao,

T hanks for testing it, and for checking the order of operations.

The Discussion: trailer points at David's message
in the CF 4997 thread; I guess it should point at this thread.

The patch came out of that thread. That message is where David said
-f should not override the check. v3 keeps it and adds this thread as
a second Discussion line.

And a
restored backup normally has tablespace_map too, while the check only
looks at backup_label; is ignoring it on purpose?

Yes. The server reads tablespace_map only when backup_label is there.
Without backup_label it renames the file to tablespace_map.old and
starts as usual. So tablespace_map alone does not stop the server from
starting, and there is nothing for pg_resetwal to guard against.
v3 also leaves out the --cluster-state patches, as David suggested.
0001 and 0002 have no code changes.

Thanks,
Shihao

#8shihao zhong
zhong950419@gmail.com
In reply to: Joao Detomini (#7)
Re: pg_resetwal: refuse to run when backup_label exists

Hi Joao,

Thanks for testing v3.

A backup_label looks like that second kind to me, so I'd keep v3
as is.

Agreed, I will leave v3 as it is.

I see the CF entry is now Waiting on Author. Is there something you
want me to change in v3? If not, I think it can go back to Needs
review, or Ready for Committer if you think it is ready.

Thanks,
Shihao

#9Joao Detomini
joao.detomini@enterprisedb.com
In reply to: shihao zhong (#8)
Re: pg_resetwal: refuse to run when backup_label exists

Hi Shihao,

Nothing to change from my side, v3 looks fine to me. I'll put it
back to Needs review for now, since Michael hasn't said whether he's
ok with -f not overriding the check.

Thanks,
João Marcelo

Em seg., 5 de out. de 2026 às 11:56, shihao zhong <zhong950419@gmail.com>
escreveu:

Show quoted text

Hi Joao,

Thanks for testing v3.

A backup_label looks like that second kind to me, so I'd keep v3
as is.

Agreed, I will leave v3 as it is.

I see the CF entry is now Waiting on Author. Is there something you
want me to change in v3? If not, I think it can go back to Needs
review, or Ready for Committer if you think it is ready.

Thanks,
Shihao

#10Michael Paquier
michael@paquier.xyz
In reply to: Joao Detomini (#9)
Re: pg_resetwal: refuse to run when backup_label exists

On Mon, Oct 05, 2026 at 12:04:14PM -0300, Joao Detomini wrote:

Nothing to change from my side, v3 looks fine to me. I'll put it
back to Needs review for now, since Michael hasn't said whether he's
ok with -f not overriding the check.

I'm maybe just not seeing the value of the patch, then, that's all, so
I doubt that my opinion has any value.

Please note that the community mailing lists follow the following
style in terms of message posting:
https://en.wikipedia.org/wiki/Posting_style#Bottom-posting
--
Michael

#11Joao Detomini
joao.detomini@enterprisedb.com
In reply to: Michael Paquier (#10)
Re: pg_resetwal: refuse to run when backup_label exists

On Mon, Oct 05, 2026 at 07:32 PM, Michael Paquier wrote:

I'm maybe just not seeing the value of the patch, then, that's all, so
I doubt that my opinion has any value.

That's fine, thanks for taking a look.

Please note that the community mailing lists follow the following
style in terms of message posting:

Noted, sorry about that.

Shihao, I'm moving the entry to Ready for Committer. The code and
tests look good to me, and the question of whether -f should be able
to override the check is left for the committer to decide.

Regards,
João Marcelo

Em seg., 5 de out. de 2026 às 19:32, Michael Paquier <michael@paquier.xyz>
escreveu:

Show quoted text

On Mon, Oct 05, 2026 at 12:04:14PM -0300, Joao Detomini wrote:

Nothing to change from my side, v3 looks fine to me. I'll put it
back to Needs review for now, since Michael hasn't said whether he's
ok with -f not overriding the check.

I'm maybe just not seeing the value of the patch, then, that's all, so
I doubt that my opinion has any value.

Please note that the community mailing lists follow the following
style in terms of message posting:
https://en.wikipedia.org/wiki/Posting_style#Bottom-posting
--
Michael

#12Tình Trần
tranvantinhnbk@gmail.com
In reply to: shihao zhong (#1)
Re: pg_resetwal: refuse to run when backup_label exists

Hi Shihao,
I have a local test result for this patch on macOS 26.6.2 (arm64).
My checkout contains v2-0001 (code/docs) and v3-0002 (tests), on base
e01fc6315f19a794301ca8889d37ae629862e2ac.

This report is for that combination, not a claim to have tested a newer
complete series. T
he build succeeded with --without-icu --enable-tap-tests. A
fter installing to a private prefix,
I ran: make -C src/bin/pg_resetwal installcheck PROVE_FLAGS=--verbose Both
runs passed: Files=2, Tests=109, Result: PASS.
The added tests cover refusal with backup_label present, including --force
and --dry-run, and successful reset and server startup after removing the
synthetic label.
One possible test enhancement would be to assert that pg_control, the WAL
files, and backup_label remain unchanged after each refusal.
Regards, Tinh

Vào Thứ 7, 10 thg 10, 2026 vào lúc 20:20 shihao zhong <
zhong950419@gmail.com> đã viết:

Show quoted text

Hi hackers,

pg_resetwal does not look for backup_label today. On a restored base
backup, pg_control says "in production", so pg_resetwal asks for -f, and
with -f it goes ahead. The server then fails with "could not locate
required checkpoint record" and a hint to remove backup_label. Removing it
at that point throws away what the backup needs to become consistent.

The attached patch makes pg_resetwal refuse when backup_label exists, even
with -f. This follows the postmaster.pid check, which -f does not override
either. It came up in the CF 4997 thread [1], and David preferred that -f
not bypass it [2]. On a pg_basebackup copy it now says:

pg_resetwal: error: backup label file "backup_label" exists
pg_resetwal: hint: If you are restoring from a backup, configure
recovery instead. If you are not restoring from a backup, delete the
backup label file and try again.

-n is refused too. A dry run should show what a real run would do, and the
real run refuses. pg_controldata still works for reading the control file.

Robert worried in [3] that people with a bad backup will just run
pg_resetwal, which is worse than starting from the wrong checkpoint. This
patch targets that step. A backup that still has its backup_label is the
case where the user has everything needed for a correct restore, and
pg_resetwal is the wrong tool. Now it says so before it does any damage. A
user can still delete the file and rerun, but that is a second deliberate
step, and the docs now say when that is safe.

0002 adds TAP tests and is optional. I think this is master only, since it
changes what an existing command accepts.

[1] /messages/by-id/e2636c5d-c031-43c9-a5d6-5e5c7e4c5514@pgmasters.net
[2]
/messages/by-id/556bef11-938d-45ca-94b3-7143a3cb532d@pgbackrest.org
[3]
/messages/by-id/CA+TgmoZkdrWyd7KiPFHaJBg+tjM3UFrqOBK1EtG3NtVs97-7Xw@mail.gmail.com

Thanks,
Shihao

#13shihao zhong
zhong950419@gmail.com
In reply to: shihao zhong (#1)
Re: pg_resetwal: refuse to run when backup_label exists

i Tinh,

Thanks for testing.

One possible test enhancement would be to assert that pg_control,
the WAL files, and backup_label remain unchanged after each refusal.

I would leave that out. The check runs before pg_resetwal reads
pg_control, right after the postmaster.pid check, so nothing has been
written at that point. The postmaster.pid refusal has no such test
either. I did check by hand, and all three are unchanged after each
refusal.

Thanks,
Shihao

#14Tình Trần
tranvantinhnbk@gmail.com
In reply to: shihao zhong (#13)
Re: pg_resetwal: refuse to run when backup_label exists

Hi Shihao,

Thanks for checking this manually. That makes
sense—the early check and consistency with the postmaster.pid

I have no further comments on this point.

Regards,
Tinh

Vào CN, 11 thg 10, 2026 vào lúc 09:32 shihao zhong <zhong950419@gmail.com>
đã viết:

Show quoted text

i Tinh,

Thanks for testing.

One possible test enhancement would be to assert that pg_control,
the WAL files, and backup_label remain unchanged after each refusal.

I would leave that out. The check runs before pg_resetwal reads
pg_control, right after the postmaster.pid check, so nothing has been
written at that point. The postmaster.pid refusal has no such test
either. I did check by hand, and all three are unchanged after each
refusal.

Thanks,
Shihao