diff --git a/src/backend/access/heap/heapam_handler.c b/src/backend/access/heap/heapam_handler.c
index 6ecd7631489..f35ccabb4ff 100644
--- a/src/backend/access/heap/heapam_handler.c
+++ b/src/backend/access/heap/heapam_handler.c
@@ -895,8 +895,17 @@ heapam_relation_copy_for_cluster(Relation OldHeap, Relation NewHeap,
 
 			Assert(BlockNumberIsValid(range_end));
 
-			/* End of the current range or wraparound? */
-			if (blkno >= range_end || blkno < range_start)
+			/*
+			 * End of the current range or wraparound?
+			 *
+			 * range_start is where the scan started and it never changes.
+			 * Once the scan has wrapped around, range_end is not above it and
+			 * the blocks before range_end are in the range too, like in
+			 * is_block_in_range().
+			 */
+			if (range_start < range_end ?
+				(blkno >= range_end || blkno < range_start) :
+				(blkno >= range_end && blkno < range_start))
 				snapshot = finalize_block_range(chgcxt, blkno, range_start,
 												&range_end);
 
@@ -1111,6 +1120,13 @@ finalize_block_range(ChangeContext *chgcxt, BlockNumber cur,
 	 * block number could have wrapped around.
 	 */
 	end = cur + repack_pages_per_snapshot - (cur % repack_pages_per_snapshot);
+
+	/*
+	 * After wraparound the scan ends right before 'start'. If the range went
+	 * beyond that, it would look like a range that has not wrapped around.
+	 */
+	if (cur < start && end > start)
+		end = start;
 	*end_p = end;
 
 	/*
