Fix #4493: NullReferenceException combining optimistic concurrency and partitioning#4496
Merged
Merged
Conversation
…d partitioning UpsertFunction's partition-column scan called arg.Column.Equals(colName, ...) on each UpsertArgument when building the partition WHERE-clause fragment. CurrentVersionArgument deliberately sets Column to null (it's a sentinel that doesn't map to a stored column), so when optimistic concurrency was enabled on a document that also participated in AllDocumentsAreMultiTenantedWith- Partitioning(...), DocumentSchema construction blew up with NullReferenceException during ApplyAllConfiguredChangesToDatabase- Async — exactly the symptom in the reporter's repro. Switch from arg.Column.Equals(...) to the null-safe string.Equals(arg.Column, colName, ...) overload. Behavior is otherwise unchanged. Regression test in src/CoreTests/Partitioning/ Bug_4493_optimistic_partitioning.cs covers the exact configuration shape from the reporter's repro: UseOptimisticConcurrency(true) on a document plus AllDocumentsAreMultiTenantedWithPartitioning with two list partitions. Verified the test reproduces the NRE without the fix and passes with it, on net8.0 / net9.0 / net10.0. Closes #4493. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
3 tasks
jeremydmiller
added a commit
that referenced
this pull request
May 19, 2026
Companion to the 8.0-line fix in #4496. The bug — NullReferenceException when combining .UseOptimisticConcurrency(true) with AllDocumentsAreMultiTenantedWithPartitioning(...) — doesn't reproduce on master because the offending code path (Marten/Storage/UpsertFunction.cs) was retired in #4461's closed-shape storage rewrite. The cherry-pick of the 8.0 patch therefore omits the UpsertFunction.cs edit (file no longer exists) and lands only the regression test. Test exercises the exact configuration shape from the reporter's repro: .UseOptimisticConcurrency(true) on a document plus AllDocumentsAreMultiTenantedWithPartitioning with two list partitions, then applies the schema and round-trips a document through one of the partitions. Acts as a regression-prevention guard against any future change that re-introduces a similar null-traversal in the partition-aware DDL generation. Passes on net9.0 / net10.0. Closes #4493. Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
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.
Summary
Closes #4493.
UpsertFunction's partition-column scan calledarg.Column.Equals(colName, ...)on eachUpsertArgumentwhen building the partition WHERE-clause fragment.CurrentVersionArgumentdeliberately setsColumntonull(it's a sentinel that doesn't map to a stored column), so when optimistic concurrency was enabled on a document that also participated inAllDocumentsAreMultiTenantedWithPartitioning(...),DocumentSchemaconstruction blew up withNullReferenceExceptionduringApplyAllConfiguredChangesToDatabaseAsync— exactly the symptom in the reporter's repro.The fix
string.Equals(null, "foo", ...)is null-safe and returnsfalse, so aCurrentVersionArgumentis naturally skipped — the only path that was crashing.Test plan
CoreTests/Partitioning/Bug_4493_optimistic_partitioning.csreproduces the exact configuration from the reporter's repro (.UseOptimisticConcurrency(true)+AllDocumentsAreMultiTenantedWithPartitioningwith two list partitions) and round-trips a document through one of the partitions.NullReferenceException at UpsertFunction.cs:127without the fix (verified locally).CoreTests.Partitioning.*) all 27 still pass.Master companion PR will follow.
🤖 Generated with Claude Code