From 7a28f1d0280ac11c12aa27e36d330e751f4285fe Mon Sep 17 00:00:00 2001 From: Peter Geoghegan Date: Thu, 15 Oct 2026 12:17:18 -0400 Subject: [PATCH] Fix _bt_readnextpage half-dead leftmost page assert. Backwards scans that reach a half-dead leftmost leaf page step over the page without calling _bt_readpage. This happens whenever the most recent _bt_lock_and_validate_left call returned a half-dead leftmost page. An assertion within _bt_readnextpage failed to consider this, causing it to fail spuriously. To fix, make the assertion accept the case where currPage doesn't match lastcurrblkno as long as blkno is P_NONE (it's always P_NONE when the last leaf page examined by _bt_readnextpage is either the leftmost or rightmost page). Oversight in commit caca6d8d27. Author: Peter Geoghegan Backpatch-through: 18 --- src/backend/access/nbtree/nbtsearch.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/src/backend/access/nbtree/nbtsearch.c b/src/backend/access/nbtree/nbtsearch.c index d47e4b20783..4b294ce6bac 100644 --- a/src/backend/access/nbtree/nbtsearch.c +++ b/src/backend/access/nbtree/nbtsearch.c @@ -2387,8 +2387,13 @@ _bt_readnextpage(IndexScanDesc scan, BlockNumber blkno, (ScanDirectionIsForward(dir) ? !so->currPos.moreRight : !so->currPos.moreLeft)) { - /* most recent _bt_readpage call (for lastcurrblkno) ended scan */ - Assert(so->currPos.currPage == lastcurrblkno && !seized); + /* + * most recent _bt_readpage call (for lastcurrblkno) ended scan, + * or lastcurrblkno is a half-dead leftmost page (not read by + * _bt_readpage, so so->currPos doesn't describe it) + */ + Assert(so->currPos.currPage == lastcurrblkno || blkno == P_NONE); + Assert(!seized); BTScanPosInvalidate(so->currPos); _bt_parallel_done(scan); /* iff !so->needPrimScan */ return false;