Projection with a collection leaf whose ELEMENT TYPE has its own eager-loaded navigation throws ArgumentException in every query mode

XMLWordPrintableJSON

    • Type: Bug
    • Resolution: Unresolved
    • Priority: Unknown
    • None
    • Affects Version/s: None
    • Component/s: None
    • None
    • Dotnet Drivers
    • None
    • None
    • None
    • None
    • None
    • None

      Summary

      A projection into an anonymous type (or DTO) whose leaf is an entity collection navigation hard-fails at translation / shaper-compilation time, identically under all three query modes: Native, DriverLinq and NativeOnly.

      The failing shape:

      db.Blogs.AsNoTracking().Select(b => new { b.Title, b.Posts }).ToList();
      

      ...where Posts is an owned collection navigation, configured with OwnsMany.

      This is pre-existing and independent of the projection-path null-collection work in EF-358, which is merely where it was measured. Applying EF-358 changes nothing about it.

      Exception

      ArgumentException: Argument type 'System.Collections.Generic.IEnumerable`1[Post]'
      does not match the corresponding member type 'System.Collections.Generic.List`1[Post]'
      (Parameter 'arguments[1]')
      

      Root cause (traced, not guessed)

      This is the validation error raised by the following overload when an anonymous-type constructor argument's static type does not match the corresponding member's declared type:

      Expression.New(ConstructorInfo, IEnumerable<Expression>, MemberInfo[])
      

      It fires while the shaper expression tree is being constructed, not while any document is read. That is why it throws identically for a well-formed, non-empty stored array as for a missing, null or empty one — the failure has nothing to do with the stored data.

      The collection leaf is supplied as a CollectionShaperExpression whose static type does not match the anonymous type's member type:

      supplied:  IEnumerable<Post>   (or List<Post>)
      expected:  List<Post>          (the anonymous type's member)
      

      This is the same family as the root cause traced for EF-357. MatchTypes passes a List-typed shaper straight through for an IQueryable or IEnumerable target rather than adapting it, because TryGetItemType() on the target type is non-null. See MongoProjectionBindingExpressionVisitor — the comment describing that hazard sits near the Queryable-method switch.

      Measured behaviour

      Measured on a Blog / Post model with OwnsMany(b => b.Posts), over four seeded documents: an array of 2 elements, an empty array, the field absent, and the field present but explicitly BSON null.

      The array-leaf projection above throws ArgumentException for the whole query in every mode, before any row's array state matters:

      • Native — throws ArgumentException.
      • DriverLinq — same ArgumentException.
      • NativeOnly — same ArgumentException, and notably not NativeTranslationNotSupportedException.

      For contrast, on the same model and the same documents:

      • The bare array projection Select(b => b.Posts) works. It returns the collection, and since EF-358 a missing or explicitly-null stored array normalizes to an empty collection.
      • Whole-entity materialization and Include(b => b.Posts) both work.

      So the defect is specific to wrapping a collection navigation as a leaf inside a constructed projection. It is not a problem with projecting collections as such.

      Why this is a bug, not an unsupported-shape decline

      Per the provider's versioning rubric, the exception type for a genuinely unsupported shape is not part of the contract. But this is not a clean decline:

      • It throws under Native and DriverLinq, where the documented behaviour for a non-native shape is to fall back to driver-LINQ and return correct results.
      • It throws ArgumentException out of BCL expression-tree validation — an internal failure — rather than the provider's own NativeTranslationNotSupportedException.

      That makes it the same shape of defect as EF-357 (bare embedded-collection .Count projection) and EF-359 (filtered Count with a predicate in a projection): a translation-time crash reached before MongoQueryMode is ever consulted, so the query mode is irrelevant to whether it fails.

      Suggested resolution

      Two options, in increasing scope:

      1. Adapt the type at the binding site, so the collection shaper's static type matches the target member. This is the narrow fix, analogous to what EF-357's fix did for Count and LongCount by rebuilding them against the Enumerable overload.
      2. Close the general MatchTypes gap. These Queryable and Enumerable shaper types are never adapted to their target, which strands First, Any, Sum and others on the same fall-through. This is the real root cause, but it changes type coercion on a path that every projection walks, in all three query modes, so it needs its own verification pass.

      At minimum the shape should decline cleanly rather than throwing ArgumentException out of expression-tree validation.

      Provenance

      Measured during EF-358 (branch tip 7c199e4 on origin/NativeQueryOngoing), Task 1 spike. Verbatim probe output and the full analysis are committed in the repo at:

      docs/superpowers/specs/2026-07-29-projection-path-null-collection-normalization-spike-findings.md
      

      Section 2 has the raw measured output. Section 5 explains why this shape was excluded from that branch's scope.

      Related: EF-357 (closed by EF-358), EF-359, and the interposed-operator family recorded as a comment on the EF-322 epic — all sharing the same fall-through root cause.

            Assignee:
            Unassigned
            Reporter:
            Arthur Vickers
            Votes:
            0 Vote for this issue
            Watchers:
            1 Start watching this issue

              Created:
              Updated: