From 1a570da7e93b81c7be488fcc4e0ff3a283320923 Mon Sep 17 00:00:00 2001
From: Laurenz Albe <laurenz.albe@cybertec.at>
Date: Thu, 25 Jul 2024 14:44:27 +0200
Subject: [PATCH v3] Document an error with incremental backup on standbys

Taking an incremental backup on a streaming replication standby immediately
after the previous backup backup can result in the error

  manifest requires WAL from final timeline n ending at XXX, but this backup starts at YYY

This message looks scary, even though the only problem is that the backup
would be empty and thus it makes no sense to take it anyway.

Add a clarifying errhint and some documentation to mitigate the problem.

Author: Laurenz Albe
Reviewed-by: Robert Haas, David Steele
Discussion: https://postgr.es/m/04f4277e5ed4046773e46837110bed1381a2583f.camel@cybertec.at

Backpatch to v17.
---
 doc/src/sgml/backup.sgml                    | 11 +++++++++++
 src/backend/backup/basebackup_incremental.c |  3 ++-
 2 files changed, 13 insertions(+), 1 deletion(-)

diff --git a/doc/src/sgml/backup.sgml b/doc/src/sgml/backup.sgml
index 91da3c26ba..e4e4c56cf1 100644
--- a/doc/src/sgml/backup.sgml
+++ b/doc/src/sgml/backup.sgml
@@ -925,6 +925,17 @@ test ! -f /mnt/server/archivedir/00000001000000A900000065 &amp;&amp; cp pg_wal/0
     to manage. For a large database all of which is heavily modified,
     incremental backups won't be much smaller than full backups.
    </para>
+
+   <para>
+    An incremental backup is only possible if replay would begin from a later
+    checkpoint than for the previous backup upon which it depends.  If you
+    take the incremental backup on the primary, this condition is always
+    satisfied, because each backup triggers a new checkpoint.  On a standby,
+    replay begins from the most recent restartpoint.  Therefore, an
+    incremental backup of a standby server can fail if there has been very
+    little activity since the previous backup, since no new restartpoint might
+    have been created.
+   </para>
   </sect2>
 
   <sect2 id="backup-lowlevel-base-backup">
diff --git a/src/backend/backup/basebackup_incremental.c b/src/backend/backup/basebackup_incremental.c
index 2108702397..a023e62440 100644
--- a/src/backend/backup/basebackup_incremental.c
+++ b/src/backend/backup/basebackup_incremental.c
@@ -441,7 +441,8 @@ PrepareForIncrementalBackup(IncrementalBackupInfo *ib,
 						 errmsg("manifest requires WAL from final timeline %u ending at %X/%X, but this backup starts at %X/%X",
 								range->tli,
 								LSN_FORMAT_ARGS(range->end_lsn),
-								LSN_FORMAT_ARGS(backup_state->startpoint))));
+								LSN_FORMAT_ARGS(backup_state->startpoint)),
+						 errhint("This can happen for incremental backups on a standby if there was little activity since the previous backup.")));
 		}
 		else
 		{
-- 
2.45.2

