From 210ed20a78e09b8f21eef3f1c22e98082b4b30b2 Mon Sep 17 00:00:00 2001
From: Baji Shaik <baji.pgdev@gmail.com>
Date: Tue, 26 May 2026 21:36:03 -0500
Subject: [PATCH 3/3] Add missing errcode() to REPACK CONCURRENTLY ereport
 calls

Four ereport(ERROR) calls in the REPACK CONCURRENTLY code path are
missing errcode(), causing them to default to ERRCODE_INTERNAL_ERROR
(XX000):

  * apply_concurrent_update(): "failed to apply concurrent UPDATE"
  * apply_concurrent_delete(): "failed to apply concurrent DELETE"
  * decode_concurrent_changes(): "could not read WAL record"
  * decode_concurrent_changes(): "waiting for WAL failed"

The first two can occur in practice when a concurrent transaction
modifies a tuple between the time it was decoded and the time REPACK
tries to apply the change.  Use ERRCODE_T_R_SERIALIZATION_FAILURE
(40001) for these, matching the semantics of a serialization conflict.
Also include the relation name in the errmsg for context.

The third indicates WAL corruption; use ERRCODE_DATA_CORRUPTED.  The
fourth is an internal failure; keep ERRCODE_INTERNAL_ERROR but make
it explicit.
---
 src/backend/commands/repack.c        | 8 ++++++--
 src/backend/commands/repack_worker.c | 2 ++
 2 files changed, 8 insertions(+), 2 deletions(-)

diff --git a/src/backend/commands/repack.c b/src/backend/commands/repack.c
index e2d405c336f..fd1e21b5f9f 100644
--- a/src/backend/commands/repack.c
+++ b/src/backend/commands/repack.c
@@ -2707,7 +2707,9 @@ apply_concurrent_update(Relation rel, TupleTableSlot *spilled_tuple,
 							 &tmfd, &lockmode, &update_indexes);
 	if (res != TM_Ok)
 		ereport(ERROR,
-				errmsg("failed to apply concurrent UPDATE"));
+				errcode(ERRCODE_T_R_SERIALIZATION_FAILURE),
+				errmsg("failed to apply concurrent UPDATE on relation \"%s\"",
+					   RelationGetRelationName(rel)));
 
 	if (update_indexes != TU_None)
 	{
@@ -2743,7 +2745,9 @@ apply_concurrent_delete(Relation rel, TupleTableSlot *slot)
 
 	if (res != TM_Ok)
 		ereport(ERROR,
-				errmsg("failed to apply concurrent DELETE"));
+				errcode(ERRCODE_T_R_SERIALIZATION_FAILURE),
+				errmsg("failed to apply concurrent DELETE on relation \"%s\"",
+					   RelationGetRelationName(rel)));
 
 	pgstat_progress_incr_param(PROGRESS_REPACK_HEAP_TUPLES_DELETED, 1);
 }
diff --git a/src/backend/commands/repack_worker.c b/src/backend/commands/repack_worker.c
index b84041372b8..a6a93fa740b 100644
--- a/src/backend/commands/repack_worker.c
+++ b/src/backend/commands/repack_worker.c
@@ -432,6 +432,7 @@ decode_concurrent_changes(LogicalDecodingContext *ctx,
 				priv->end_of_wal = false;
 			else
 				ereport(ERROR,
+						errcode(ERRCODE_DATA_CORRUPTED),
 						errmsg("could not read WAL record"));
 		}
 
@@ -479,6 +480,7 @@ decode_concurrent_changes(LogicalDecodingContext *ctx,
 			if (res != WAIT_LSN_RESULT_SUCCESS &&
 				res != WAIT_LSN_RESULT_TIMEOUT)
 				ereport(ERROR,
+						errcode(ERRCODE_INTERNAL_ERROR),
 						errmsg("waiting for WAL failed"));
 		}
 	}
-- 
2.50.1 (Apple Git-155)

