From 407c6b4ab695956bb9f207efddf477d130c820ba Mon Sep 17 00:00:00 2001
From: Laurenz Albe <laurenz.albe@cybertec.at>
Date: Wed, 24 Jul 2024 12:42:24 +0200
Subject: [PATCH v2] Add documentation and hint for 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..13b60c39bb 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 the checkpoint that started 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

