Fix #4557: deliver the events source generator to consumers + consume JasperFx.Events 2.1.1#4558
Merged
Merged
Conversation
…rator A self-aggregating immutable record snapshot with static Create/Apply, registered via Projections.Snapshot<MyType>(Inline), worked in Marten 8 (runtime codegen) but throws at DocumentStore.For(...) in Marten 9: InvalidProjectionException: No source-generated dispatcher found for SingleStreamProjection<MyType, Guid>... Root cause: the JasperFx.Events.SourceGenerator analyzer is referenced by Marten with PrivateAssets=all, so it never flows to a consumer that only references the Marten package. With no analyzer in the consumer assembly, Pipeline 3 (Snapshot<T> call-site detection) never emits a [GeneratedEvolver], and JasperFxAggregationProjectionBase.AssembleAndAssertValidity fail-fasts — there is no runtime evolver fallback for conventional methods, despite the migration guide promising one. Repro types + Snapshot<T> registration live in Marten.Testing.OtherAssembly (references Marten, no analyzer) to mirror a real consumer. Confirmed: adding ONLY the analyzer package to the user's sample (no code change) makes it work. - throws_at_registration: green, pins the current failure - should_round_trip: skipped, the desired post-fix behavior Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
B — Marten now bundles the JasperFx.Events.SourceGenerator analyzer in its own NuGet package (analyzers/dotnet/cs) via a per-TFM pack hook. Marten 9 requires a source-generated evolver for conventional Apply/Create/ShouldDelete projections (there is no runtime fallback — that was the deliberate goal of the 9.0 projections rework), but the generator ships as a DevelopmentDependency that does not flow transitively, so a consumer referencing only the Marten package never ran it and hit "No source-generated dispatcher found ..." at DocumentStore.For(). Carrying the analyzer in Marten's package makes a plain `<PackageReference Include="Marten" />` sufficient. Validated by packing Marten locally and running the issue's reproduction sample unmodified (non-partial record, no analyzer reference): it now round-trips. C — Corrected the migration guide, which wrongly promised "Marten falls back to runtime evolver lookup" for non-partial convention projections. There is no such fallback; documented that the generator now ships inside the Marten package, that self-aggregating Snapshot<T> types do NOT need to be `partial` (only projection subclasses do), and that it must run in the assembly defining the aggregate type. Test refinement: the reproduction documents the runtime fail-fast when the analyzer is absent from the aggregate's assembly (ProjectReference consumers can't observe the NuGet bundling, so the package fix is validated via packaging instead). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
- JasperFx.Events + JasperFx.Events.SourceGenerator 2.1.0 -> 2.1.1, which carries #367: the source generator now emits a self-aggregating evolver for `record` aggregates from their own declaration (parity with classes — no Snapshot<T> call site and no `partial` required), fixing the cross-assembly gap. Marten bundles this analyzer, so the bundled copy now carries the fix. - Marten <Version> 9.0.1 -> 9.0.2. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This was referenced May 25, 2026
This was referenced Jun 2, 2026
This was referenced Jun 4, 2026
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 #4557.
Problem
A user upgrading 8 → 9 with a self-aggregating immutable
recordsnapshot (staticCreate/Apply, registered viaProjections.Snapshot<MyType>(Inline)) hit this atDocumentStore.For(...):It worked in v8 (runtime codegen). Marten 9 dispatches conventional
Apply/Create/ShouldDeletethrough the compile-timeJasperFx.Events.SourceGeneratorand has no runtime fallback — but the generator ships as aDevelopmentDependencyreferenced withPrivateAssets=all, so it never flowed to a consumer that only references theMartenpackage. The generator simply never ran, so no[GeneratedEvolver]was emitted and the runtime fail-fasted.Confirmed by adding only the analyzer package to the user's sample (zero code change) → it round-trips.
Fix
Marten.csproj): a per-TFMTargetsForTfmSpecificContentInPackagehook shipsJasperFx.Events.SourceGenerator.dllinanalyzers/dotnet/cs, so a plain<PackageReference Include="Marten" />applies the generator automatically. Validated by packing Marten locally and running the issue's sample unmodified (non-partialrecord, no analyzer reference) →Snapshot found: True.Directory.Packages.props): jasperfx#367 makes the generator emit a self-aggregating evolver forrecordaggregates from their own declaration (parity with classes — noSnapshot<T>call site, nopartial), which also closes the cross-assembly case (aggregate defined in one assembly, registered in another). The bundled analyzer now carries this fix.migration-guide.md): removed the incorrect "Marten falls back to runtime evolver lookup" claim; documented that there is no runtime fallback, that the generator ships inside the Marten package, and that self-aggregatingSnapshot<T>types do not need to bepartial(only projection subclasses do).Tests
Bug_4557_self_aggregating_snapshot_without_source_generatordocuments the runtime fail-fast when the analyzer is absent from the aggregate's assembly (repro types inMarten.Testing.OtherAssembly, a ProjectReference consumer that — by design — can't observe the NuGet bundling; the package fix is validated via packaging).dotnet restore+ Release build clean on the 2.1.1 pins; the bundled-analyzer path resolves tojasperfx.events.sourcegenerator/2.1.1.🤖 Generated with Claude Code