-
Type:
Bug
-
Resolution: Fix Not Needed
-
Priority:
Unknown
-
None
-
Affects Version/s: None
-
Component/s: None
-
None
-
None
-
Dotnet Drivers
-
Not Needed
-
None
-
None
-
None
-
None
-
None
-
None
Summary
EF-379 built, and then withdrew, a decline for a transitive join hop that has no resolvable intermediate. This ticket is to reinstate it with a discriminator that actually works. The withdrawal is recorded here so the same mistake is not repeated.
What was built
In RebindInnerShaperToOuterQuery, after the transitive scan over outerQueryExpression.InnerCollections:
if (hopKind == JoinHopKind.TransitiveHop && navigation == null) { return null; }
Rationale: a hop classified transitive but with no matching prior inner collection has no intermediate to be scoped under, so no $lookup is registered for it at all and the shaper reads a field nothing wrote. Declining turned a self-referencing two-hop chain's raw InvalidOperationException: Document element is missing for required non-nullable property 'Id' into a clean translation failure carrying AddTranslationErrorDetails.
Why it was withdrawn – MEASURED regression
A transparent identifier is not produced only by a prior join. An owned SelectMany produces one too, so the FIRST TranslateJoinCore call can see a ti.Inner receiver, classify transitive, find no candidate (the scan skips priorInnerEntityType == innerEntityType), and hard-fail a query that previously worked:
from o in db.Orders from t in o.Tags // OwnsMany; Tag has an ObjectId ProductId FK property, NO navigation join p in db.Products on t.ProductId equals p.Id select new { o.Total, p.Name }
| tree | Native | DriverLinq |
|---|---|---|
| base 2a544b7e | OK, 3 rows | OK, 3 rows |
| with the decline | InvalidOperationException | InvalidOperationException |
Instrumentation recorded 11 decline firings over 4 distinct shapes in the EF10 functional ~Query filter alone, every one at InnerCollections.Count == 1, including the committed test NativeSelectManyTests.Reference_form_bare_entity_with_cross_collection_autoinclude_declines_cleanly_in_every_mode – which stayed green only because it already asserted Throws<InvalidOperationException>, so the suite could not have caught the regression class.
Constraints on any fix
- *InnerCollections.Count > 1 is NOT a usable gate.* The self-referencing case is also Count == 1, because InnerCollections is keyed by IEntityType and both hops collapse to one entry – the same entity-type-keyed blind spot as
EF-375. - The discriminator must separate "the Inner came from a prior JOIN" from "the Inner came from a SelectMany unwind". MongoSelectDefinition.UnwindSources is the obvious place to look.
- *Do not assume receiver shape implies join ordinal.* That premise (bare parameter = first join, TI chain = second-or-later) is what produced this regression; it was scrubbed from the spike doc, the code comments and the status report.
- The regression is pinned by Ef379RootNavigationMisroutingTests.Owned_SelectMany_then_join_off_the_unwound_element_still_works, which goes red if the decline is re-added verbatim (mutation D: 7 of 19 cases red across 3 methods).
What reinstating it would buy
- The self-referencing two-hop chain gets a clean decline instead of a materialization crash. It does not start WORKING – the scan's priorInnerEntityType == innerEntityType skip and navigation-name-only alias dedup both block that, the same blocker as the sibling-ThenInclude case in
EF-376. - NorthwindNavigationsQueryMongoTest.Select_Where_Navigation_Null_Deep would move off its
EF-371known-wrong-data baseline (currently 0 rows where 6 are correct) to a translation failure. With the decline in place that test passed under NativeOnly and the EF10 spec axis showed +2; both were reverted with the withdrawal.
Status
Unreleased path – cross-collection joins do not translate at all at v10.0.2 / v9.1.2 / v8.4.2, so no BREAKING-CHANGES.md entry applies.
From the EF-379 review (2026-08-05, branch NativeQueryOngoing, tip 9065acfc).