Skip to content

Fix codegen for WriteAggregate with OnMissing.ThrowException and batch queries#2390

Merged
jeremydmiller merged 1 commit intomainfrom
fix-write-aggregate-throw-codegen
Mar 31, 2026
Merged

Fix codegen for WriteAggregate with OnMissing.ThrowException and batch queries#2390
jeremydmiller merged 1 commit intomainfrom
fix-write-aggregate-throw-codegen

Conversation

@jeremydmiller
Copy link
Copy Markdown
Member

Summary

Fixes #2387

  • Root cause: When using [WriteAggregate(OnMissing = ThrowException)] with UseIdentityMapForAggregates = true and a Validate() middleware method, the Marten batch query policy enrolled the LoadAggregateFrame in a batch but didn't emit the variable declaration (var stream_entity = await stream_entity_BatchItem) until after guard frames had already tried to reference stream_entity.Aggregate, causing CS0841: Cannot use local variable before it is declared.
  • Fix: Added GenerateCodeForBatchResolution() to LoadAggregateFrame, called by MartenBatchFrame immediately after batchQuery.Execute(). This ensures the stream variable is declared before any guard frames (null checks, Validate calls) reference it. The original GenerateCode() skips re-declaration when batch resolution has already run.

Key conditions to reproduce

All three must be present:

  1. [WriteAggregate(OnMissing = OnMissing.ThrowException)] on a message handler (not HTTP endpoint)
  2. UseIdentityMapForAggregates = true (no snapshot projection)
  3. A Validate() middleware method that takes the aggregate as a parameter

Test plan

  • 2 new reproducing tests pass (codegen compiles, throws on missing aggregate)
  • Aggregate handler workflow tests: 17/17 passed
  • Marten HTTP tests: 65/65 passed

🤖 Generated with Claude Code

…hing

When using [WriteAggregate(OnMissing = ThrowException)] with
UseIdentityMapForAggregates and a Validate() middleware method,
the codegen generated guard frames that referenced stream_entity
before it was declared. The batch query enrolled the LoadAggregateFrame
but the variable declaration (var stream_entity = await ...BatchItem)
was not emitted until after the guard frames had already tried to
use stream_entity.Aggregate.

The fix adds GenerateCodeForBatchResolution() to LoadAggregateFrame
which is called by MartenBatchFrame after the batch execute completes,
ensuring the stream variable is declared before any guard frames
reference it.

Fixes #2387

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Codegen fails with WriteAggregate on non Endpoint handler with attribute [WriteAggregate(OnMissing = Wolverine.Persistence.OnMissing.ThrowException)]

1 participant