[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
Open
[release/10.0] Fix 'ordinal -1 is invalid' crash when a nested JSON complex sub-collection grows#38373Copilot wants to merge 5 commits into
Copilot wants to merge 5 commits into
Conversation
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
There was a problem hiding this comment.
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 skipAddedflattened complex entries (behindMicrosoft.EntityFrameworkCore.Issue38299quirk 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. |
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
cincuranet
approved these changes
Jun 9, 2026
Member
artl93
approved these changes
Jun 11, 2026
artl93
left a comment
Member
There was a problem hiding this comment.
Approved. Customer reported in new scenario. Added quirk.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fixes #38299
Description
EF Core 10 introduced an issue in complex-type change tracking. When an entity maps 2+
ComplexPropertycolumns withToJson(), and a nested JSON collection item defines 2+Listsub-collection properties, growing one of those sub-collections between load and save causesSaveChangesAsyncto throwInvalidOperationException: Complex entry original ordinal '-1' is invalid ... as it's outside of the collection of length '1'. Root cause:InternalEntryBase.SetPropertyModified'srecurseloop forced every flattened complex-collection element — including newlyAddedones (whose original ordinal is legitimately-1) — toModified/Unchanged, which then failedValidateOrdinal(original: true). The fix skipsAddedcomplex entries in that loop (leaving their state as computed by change detection), mirroring the guard already present in the bulkInternalComplexCollectionEntrystate-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 —SaveChangesthrows 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_jsonto the relationalComplexCollectionJsonUpdateTestBase. 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
Addedcomplex entries during the recurse state-forcing loop, mirroring logic already present in the bulk state-change path. It is gated behind theMicrosoft.EntityFrameworkCore.Issue38299quirk switch, so the prior behavior can be restored via AppContext switch if a regression is discovered.