Subject: [PATCH 2/2] Suppress decoding of both main and TOAST tuple in REPACK (CONCURRENTLY).

From: Antonin Houska <[email-masked]>
Date: Wed, 2 Sep 2026 19:28:37 +0200

REPACK (CONCURRENTLY) suppresses logical decoding of data changes applied to
the new heap. Due to an oversight, the suppression was not propagated to the
TOAST relation in heap_update(). This can cause crash if another backend is
decoding the changes generated by REPACK. In particular,
ReorderBufferToastReplace() can end up with segfault when trying to add
TOASTed attributes to the new tuple which is actually NULL.
---
 src/backend/access/heap/heapam.c | 12 +++++++++++-
 1 file changed, 11 insertions(+), 1 deletion(-)

diff --git a/src/backend/access/heap/heapam.c b/src/backend/access/heap/heapam.c
index 72d6541734c..1c4edc14395 100644
--- a/src/backend/access/heap/heapam.c
+++ b/src/backend/access/heap/heapam.c
@@ -3961,8 +3961,18 @@ l2:
 		 */
 		if (need_toast)
 		{
+			int		toast_options = 0;
+
+			/*
+			 * If logical decoding is not needed, make sure that neither TOAST
+			 * changes are decoded.
+			 */
+			if (!walLogical)
+				toast_options |= TABLE_INSERT_NO_LOGICAL;
+
 			/* Note we always use WAL and FSM during updates */
-			heaptup = heap_toast_insert_or_update(relation, newtup, &oldtup, 0);
+			heaptup = heap_toast_insert_or_update(relation, newtup, &oldtup,
+												  toast_options);
 			newtupsize = MAXALIGN(heaptup->t_len);
 		}
 		else
-- 
2.52.0

--=-=-=--