Summary
GetLookupAlias derives a $lookup alias from the navigation name only, and AddLookup de-duplicates on As. When two hops of a query derive the same alias, only one $lookup can ever be emitted no matter what localField prefix it carries. This makes sibling {{ThenInclude}}s over two same-typed navigations impossible to translate natively.
Measured 2026-08-05 while implementing EF-372 (branch EF-372, EF10, real atlas-local container).
Repro
Model: Root.PrimaryMid and Root.SecondaryMid both reference Mid; Mid.Leaf references Leaf.
db.Roots.Include(r => r.PrimaryMid).ThenInclude(m => m.Leaf)
.Include(r => r.SecondaryMid).ThenInclude(m => m.Leaf)
Before EF-372: returned PrimaryMid.Leaf.Label == "A", SecondaryMid.Leaf == null — silently wrong data, with the two seeded leaves pointing at different targets.
After EF-372: declines translation cleanly (return null, EF Core's translation-failure path). Pinned by Two_same_typed_navigations_sibling_ThenIncludes_decline_cleanly in tests/MongoDB.EntityFrameworkCore.FunctionalTests/Query/Ef372DeepReferenceIncludeTests.cs, which asserts the decline and documents why.
Note the related shapes that do work after EF-372, so this ticket is specifically about the sibling case:
- Single-branch Include(PrimaryMid).ThenInclude(Leaf) on the same model — correct rows.
- Single-branch Include(SecondaryMid).ThenInclude(Leaf) alone — correct rows (previously returned SecondaryMid == null, silently wrong).
Root cause
Both sibling hops derive the identical alias from the same navigation name (Leaf), so AddLookup's de-dup on As drops one of them. The localField prefix work in EF-372 scopes where a lookup reads from; it cannot help when the lookup was never emitted.
Fix shape
A path-scoped alias scheme: aliases must encode the navigation path to the hop, not just the leaf navigation name, so PrimaryMid.Leaf and SecondaryMid.Leaf produce distinct aliases. This is a broader change than EF-372 and was deliberately kept out of that slice.
Any fix must keep the EF-372 invariant intact — a transitive hop's localField is scoped to the alias of the lookup that produced its intermediate — and must not disturb the contiguous-lookup-group reasoning at MongoEFToLinqTranslatingExpressionVisitor.LeftJoin.cs:695, which EF-373 depends on.
Status
Unreleased: the whole native transitive-join path postdates v10.0.2 / v9.1.2 / v8.4.2 (it arrived with efb5f256, EF-117). At those release tags any cross-collection Include/Join throws, so no shipped behavior is affected and no BREAKING-CHANGES.md entry applies.
The decline is a hard translation failure in every MongoQueryMode, including explicit DriverLinq — UseQueryMode is not an escape hatch. This is structural rather than an oversight: a transitive hop is always a second-or-later join, so lookups are registered at translation time before MongoQueryMode is read, and both paths are already committed to the flat lookup<Nav> shape. A graceful MarkNotNativelyRepresentable() was tried and measured worse — the un-rebound inner shaper reaches materialization and throws Document element is missing for required non-nullable property 'Label' under both Native and DriverLinq.