-
Type:
Task
-
Resolution: Fixed
-
Priority:
Major - P3
-
Affects Version/s: None
-
Component/s: Btree
-
Storage Engines - Foundations, Storage Engines - Persistence, Storage Engines - Transactions
-
186.874
-
SE Foundations - 2026-08-04
-
5
Problem
When a disaggregated-storage follower picks up a new layered table, it copies the leader's stable file: metadata - including the leader-assigned btree id - straight into its local metadata, without checking that the id is not already used by another local stable file (__disagg_apply_checkpoint_meta, src/conn/conn_layered_checkpoint_pick_up.c, the new-table branch, FIXME at line 680).
If that id collides with an existing local stable file, the follower opens the new table's handle over the wrong btree. Reads then resolve against another tree's blocks and history-store entries - silent data corruption, or in the block manager's stricter path a bare WT_ERROR.
The known cause of such a collision - a leader create/drop/create that leaves stale local metadata behind on a pure follower - is fixed by WT-18068 (the pickup-side drop path, WT-17746), which removes the stale entry so no id survives to alias. This ticket does not duplicate that prevention. It adds the backstop: if a collision ever reaches pickup anyway - a regression of the drop path, a race, an id-allocation bug, or a non-drop path - the follower must fail loudly before it opens the wrong btree, rather than serve corrupt reads.
The follower cannot resolve such a collision on its own. The stable id is the leader's authoritative key into shared storage (the block manager addresses every page by table_id), so the follower cannot renumber the incoming table, and it cannot delete the colliding local table without losing live data. Halting is the only safe response.
Fix
Detect a duplicate stable btree id during checkpoint pickup and panic.
- While the pickup merge loop already walks the local and shared metadata, collect the stable btree id of every .wt_stable file it processes. After the walk, detect any duplicate id and WT_ERR_PANIC naming both URIs. This reuses the sort-and-adjacent-compare logic already in __verify_unique_btree_ids (src/btree/bt_vrfy.c:254) but runs it over the ids gathered in-memory, so it adds no second metadata scan. Panicking mid-pickup is safe: it stops the connection before any handle opens over the wrong btree.
- Match the existing strict-mode failure style (WT_ERR_PANIC at lines 658 and 722).
- Optional secondary tripwire: in the new-table branch the ingest-table lookup (md_write_cursor->search) returning a hit rather than WT_NOTFOUND means an orphaned ingest table survived a drop. With WT-18068 in, that should never happen; treat it as a panic as well. This needs no extra lookup - the search already runs.
- Retag the code comment at line 680 from FIXME-
WT-14730to FIXME-WT-18150.
Test
Extend the create/drop/create coverage in test_layered_schema14. Add a case that injects a stable file: metadata entry whose id duplicates an existing local stable file, then triggers a pickup, and assert the follower panics rather than opening the wrong btree or returning a silent wrong-tree read.
- is related to
-
WT-18068 Follower reads stale btree ID after leader create/drop/create of a layered table
-
- In Code Review
-
-
WT-18190 Apply the disaggregated checkpoint pickup's local metadata updates in a single transaction
-
- Closed
-
-
WT-17746 Handle table drop during checkpoint pick-up
-
- Open
-
-
WT-14730 Validate immutable metadata config fields on checkpoint pickup
-
- Closed
-
- related to
-
WT-18068 Follower reads stale btree ID after leader create/drop/create of a layered table
-
- In Code Review
-
-
WT-17746 Handle table drop during checkpoint pick-up
-
- Open
-
- split to
-
WT-14730 Validate immutable metadata config fields on checkpoint pickup
-
- Closed
-