Skip to content

[release/10.0] Fix 'ordinal -1 is invalid' crash when a nested JSON complex sub-collection grows#38373

Open
Copilot wants to merge 5 commits into
release/10.0from
copilot/fix-invalid-ordinal-error
Open

[release/10.0] Fix 'ordinal -1 is invalid' crash when a nested JSON complex sub-collection grows#38373
Copilot wants to merge 5 commits into
release/10.0from
copilot/fix-invalid-ordinal-error

Conversation

Copilot AI commented Jun 6, 2026

Copy link
Copy Markdown
Contributor

Fixes #38299

Description
EF Core 10 introduced an issue in complex-type change tracking. When an entity maps 2+ ComplexProperty columns with ToJson(), and a nested JSON collection item defines 2+ List sub-collection properties, growing one of those sub-collections between load and save causes SaveChangesAsync to throw InvalidOperationException: Complex entry original ordinal '-1' is invalid ... as it's outside of the collection of length '1'. Root cause: InternalEntryBase.SetPropertyModified's recurse loop forced every flattened complex-collection element — including newly Added ones (whose original ordinal is legitimately -1) — to Modified/Unchanged, which then failed ValidateOrdinal(original: true). The fix skips Added complex entries in that loop (leaving their state as computed by change detection), mirroring the guard already present in the bulk InternalComplexCollectionEntry state-change path.

Customer impact
Customers using JSON-mapped complex types with the common "upsert" pattern (load a tracked entity, map incoming data onto it via Mapperly/AutoMapper/manual assignment, then SaveChanges) cannot save when a nested sub-collection grows — SaveChanges throws and the update is lost. There is no clean workaround for real upsert scenarios short of detaching/reattaching or avoiding any growth in nested collections.

How found
Customer reported on 10.0.7. The issue has 4 reactions (3 👍), indicating more than one affected customer.

Regression
No. Complex collection support was introduced in EF Core 10.0.

Testing
Added Grow_nested_sub_collection_in_complex_property_mapped_to_json to the relational ComplexCollectionJsonUpdateTestBase. Also verified end-to-end against a standalone repro matching the issue's model in both directions.

Risk
Low. The change is a narrow guard that skips Added complex entries during the recurse state-forcing loop, mirroring logic already present in the bulk state-change path. It is gated behind the Microsoft.EntityFrameworkCore.Issue38299 quirk switch, so the prior behavior can be restored via AppContext switch if a regression is discovered.

Copilot AI and others added 3 commits June 6, 2026 02:43
Co-authored-by: AndriySvyryd <6539701+AndriySvyryd@users.noreply.github.com>
Co-authored-by: AndriySvyryd <6539701+AndriySvyryd@users.noreply.github.com>
Co-authored-by: AndriySvyryd <6539701+AndriySvyryd@users.noreply.github.com>
Copilot AI changed the title [WIP] Fix InvalidOperationException on SaveChangesAsync for ComplexProperty Fix 'ordinal -1 is invalid' crash when a nested JSON complex sub-collection grows Jun 6, 2026
Copilot AI requested a review from AndriySvyryd June 6, 2026 03:17
@AndriySvyryd AndriySvyryd requested a review from Copilot June 8, 2026 19:41

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Fixes an ordinal -1 is invalid crash in EF Core change tracking when nested JSON-mapped complex sub-collections grow between load and save, by preventing Added complex entries (which legitimately have no original ordinal) from being forced into Modified/Unchanged during recursive state propagation.

Changes:

  • Updated InternalEntryBase.SetPropertyModified(..., recurse: true) to skip Added flattened complex entries (behind Microsoft.EntityFrameworkCore.Issue38299 quirk switch).
  • Added a relational specification test covering a deep JSON complex graph where one nested sub-collection grows (with a sibling sub-collection present).
  • Added SQLite functional test override with SQL baseline for the new scenario.

Reviewed changes

Copilot reviewed 4 out of 4 changed files in this pull request and generated 1 comment.

File Description
src/EFCore/ChangeTracking/Internal/InternalEntryBase.cs Skips Added complex entries during recursive state propagation to avoid invalid original-ordinal validation.
src/EFCore/ChangeTracking/Internal/InternalEntryBase.InternalComplexCollectionEntry.cs Introduces UseOldBehavior38299 AppContext switch to gate the new behavior.
test/EFCore.Relational.Specification.Tests/Update/ComplexCollectionJsonUpdateTestBase.cs Adds deep JSON model + regression test exercising nested sub-collection growth.
test/EFCore.Sqlite.FunctionalTests/Update/ComplexCollectionJsonUpdateSqliteTest.cs Adds provider override asserting the SQL update for the new test.

Comment thread src/EFCore/ChangeTracking/Internal/InternalEntryBase.cs Outdated
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
@AndriySvyryd AndriySvyryd marked this pull request as ready for review June 8, 2026 20:10
@AndriySvyryd AndriySvyryd requested a review from a team as a code owner June 8, 2026 20:10
Copilot AI review requested due to automatic review settings June 8, 2026 20:10

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 4 out of 4 changed files in this pull request and generated 1 comment.

@AndriySvyryd AndriySvyryd requested a review from cincuranet June 8, 2026 20:14
@AndriySvyryd AndriySvyryd changed the title Fix 'ordinal -1 is invalid' crash when a nested JSON complex sub-collection grows [release/10.0] Fix 'ordinal -1 is invalid' crash when a nested JSON complex sub-collection grows Jun 8, 2026
@AndriySvyryd AndriySvyryd requested a review from artl93 June 8, 2026 20:15
@AndriySvyryd

Copy link
Copy Markdown
Member

@artl93

@artl93 artl93 left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Approved. Customer reported in new scenario. Added quirk.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

ComplexProperty ToJson(): SaveChangesAsync throws 'ordinal -1 is invalid' when nested sub-collection grows (2+ JSON columns)

5 participants