From 950e0942d0960fe57d25d8101363cf8db361df3c Mon Sep 17 00:00:00 2001
From: Shihao <zhong950419@gmail.com>
Date: Mon, 28 Sep 2026 00:06:56 -0700
Subject: [PATCH v2 1/4] pg_resetwal: Refuse to run when backup_label exists

A backup_label file means the data directory is a base backup that
still needs WAL replay. Resetting WAL there leaves a corrupt cluster,
so refuse even with --force, and tell the user to set up recovery.

Discussion: https://postgr.es/m/556bef11-938d-45ca-94b3-7143a3cb532d@pgbackrest.org
---
 doc/src/sgml/ref/pg_resetwal.sgml | 14 +++++++++++++-
 src/bin/pg_resetwal/pg_resetwal.c | 19 +++++++++++++++++++
 2 files changed, 32 insertions(+), 1 deletion(-)

diff --git a/doc/src/sgml/ref/pg_resetwal.sgml b/doc/src/sgml/ref/pg_resetwal.sgml
index d34aa26413c..229cf34f00b 100644
--- a/doc/src/sgml/ref/pg_resetwal.sgml
+++ b/doc/src/sgml/ref/pg_resetwal.sgml
@@ -74,6 +74,17 @@ PostgreSQL documentation
    corrupted control file.
   </para>
 
+  <para>
+   <command>pg_resetwal</command> refuses to run on a data directory that
+   contains a <filename>backup_label</filename> file, even with
+   <option>-f</option> or <option>-n</option>.  Such a data directory is a
+   base backup that needs WAL replay to become consistent, and resetting the
+   WAL would leave it corrupted.  To restore a backup, configure recovery as
+   described in <xref linkend="backup-pitr-recovery"/>.  Remove
+   <filename>backup_label</filename> only if you are sure the data directory
+   is not a backup that still needs recovery.
+  </para>
+
   <para>
    After running this command on a data directory with corrupted WAL or a
    corrupted control file, it should be possible to start the server,
@@ -132,7 +143,8 @@ PostgreSQL documentation
       it could be dangerous, as explained above.  Specifically, this option is
       required to proceed if the server had not been cleanly shut down or if
       <command>pg_resetwal</command> cannot determine valid data for
-      <filename>pg_control</filename>.
+      <filename>pg_control</filename>.  It does not override the check for
+      a <filename>backup_label</filename> file.
      </para>
     </listitem>
    </varlistentry>
diff --git a/src/bin/pg_resetwal/pg_resetwal.c b/src/bin/pg_resetwal/pg_resetwal.c
index 634d966da9e..bc81463c180 100644
--- a/src/bin/pg_resetwal/pg_resetwal.c
+++ b/src/bin/pg_resetwal/pg_resetwal.c
@@ -431,6 +431,25 @@ main(int argc, char *argv[])
 		exit(1);
 	}
 
+	/*
+	 * A backup_label file means this is a base backup that needs WAL replay
+	 * to become consistent.  Resetting WAL cannot fix that, so refuse even
+	 * with -f.
+	 */
+	if ((fd = open(BACKUP_LABEL_FILE, O_RDONLY, 0)) < 0)
+	{
+		if (errno != ENOENT)
+			pg_fatal("could not open file \"%s\" for reading: %m",
+					 BACKUP_LABEL_FILE);
+	}
+	else
+	{
+		pg_log_error("backup label file \"%s\" exists", BACKUP_LABEL_FILE);
+		pg_log_error_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.");
+		exit(1);
+	}
+
 	/*
 	 * Attempt to read the existing pg_control file
 	 */
-- 
2.37.1 (Apple Git-137.1)

