From 2d936ccea561a9acb2e418f9b3b9c42e1372670f Mon Sep 17 00:00:00 2001
From: Antonin Houska <ah@cybertec.at>
Date: Wed, 2 Sep 2026 19:28:37 +0200
Subject: [PATCH 2/2] Suppress decoding of both main and TOAST tuple in REPACK
 (CONCURRENTLY).

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

