-
Type:
Bug
-
Resolution: Fixed
-
Priority:
Major - P3
-
Affects Version/s: None
-
Component/s: None
-
None
-
Storage Execution
-
Fully Compatible
-
ALL
-
-
Storage Execution 2026-08-31, Storage Execution 2026-09-14
-
200
-
None
-
None
-
None
-
None
-
None
-
None
-
None
Bug
Symptom
Collection validation fails due to an incorrect fast size or count after collection updates with {multi: true}, batched deletes, and/or batched inserts.
This is only an in-memory state issue, meaning that the correct size and count is still durable. Restarting the node restores the correct size and count.
Cause
Summary
In ReplicatedFastCountManager::commit(), the following catalog lookup can erroneously miss a newly created collection:
const Collection* collection = catalog->lookupCollectionByUUID(opCtx, uuid); // In a single WUOW, if the collection size/count is changed and then the collection is // dropped, the collection will be removed from the catalog before we attempt to write these // uncommitted size/count changes. So, we necessarily skip updating the collection's record // store. if (!collection) { continue; }
If a collection is durable in the _mdb_catalog WiredTiger table but not yet written to the CollectionCatalog, catalog lookups can fail to find the collection. ReplicatedFastCountManager::commit() then skips updating this collection's replicated metadata, resulting in an incorrect in-memory size and count.
Explanation
Collection acquisitions use CollectionCatalog::establishConsistentCollection() to cache an OpenedCollection with the associated RecoveryUnit::Snapshot. CollectionCatalog::lookupCollectionByUUID() checks, among other things, for an OpenedCollection with the provided UUID.
A RecoveryUnit has one OperationContext, one or more RecoveryUnit::Snapshots, and one or more WriteUnitOfWorks. If the RecoveryUnit::Snapshot containing the OpenedCollection is reset, subsequent collection catalog lookups will not see the collection create.
Reproducible Example
See the attached diff for a reproducible example which was generated by Claude. In short, when a collection write that uses multiple RecoveryUnit::Snapshots for the same collection acquisition races with that collection's creation, the UncommittedFastCountChanges are not committed.
Solution
To fix this problem, ReplicatedFastCountManager::commit() should not lookup the UUID's RecordStore instance through the collection catalog. Rather, the UncommittedFastCountChanges::_tracking map should store a shared pointer to the RecordStore and mutate it directly.