`DocumentStorage::loadLazyMetadata()` unconditionally consumes `$`-prefixed BSON fields matching internal metadata names (e.g. `$textScore`, `$pt`, `$changeStreamControlEvent`) even when the BSON comes from user data (via `$literal`, `$setField`, etc.). This causes silent metadata corruption, type-mismatch errors, and occasional crashes — most visibly on cross-shard aggregations where the merge step serializes user fields alongside real metadata.
The fix ships in three commits:
- #51366 — Guard `loadLazyMetadata()`
Add a `_bsonHasMetadata` guard so user-supplied `$`-prefixed fields are not reinterpreted as metadata on single-shard documents. Matches the existing check in the document field iterator (`shouldSkipDeleted()`).
- #51679 — Strip collisions during cross-shard merge
Introduce `Document::toBsonStrippingMetadata()` so the cross-shard merge serialization strips metadata-colliding user fields before appending real metadata. Also adds a `DocumentStorage::findField` guard that hides metadata-named fields from the document lookup API, so they are only accessible through the metadata API.
- #52144 — Warn when stripping
Log a rate-limited (one per second, via `logv2::SeveritySuppressor`) WARNING when (2) strips a field, so operators have visibility into fields being dropped. The field name is wrapped in `redact()`, so it shows as `###` in deployments running with `--redactClientLogData`.
- related to
-
SERVER-119464 Aggregation pipeline with $match: { $text }, $sort, $project gives an error
-
- In Code Review
-