Fix CultureNotFoundException in ProjectionGraph.IsAssemblyKnownToHaveNoEvolvers under invariant-globalization mode#200
Merged
jeremydmiller merged 1 commit intomainfrom Apr 30, 2026
Conversation
…NoEvolvers The cold-start optimization in DiscoverGeneratedEvolvers calls `assembly.GetName().Name` to do a cheap string-prefix check before paying for the GetCustomAttributes reflection on framework assemblies. `Assembly.GetName()` walks `AssemblyName.GetLocale()` under the hood, which calls `CultureInfo.GetCultureInfo(name)`. Under globalization-invariant mode (`<InvariantGlobalization>true</InvariantGlobalization>` — implied by NativeAOT publishing) that lookup throws `CultureNotFoundException` for any culture-tagged satellite assembly such as `pt-br`. This crashes Marten's `DocumentStore..ctor` at host build time on AOT-prepped apps that happen to have a localized assembly loaded. Use `Assembly.FullName` and split on the first comma to get the simple name. FullName is pre-cached on the runtime assembly and doesn't go through CultureInfo. Wrap in try/catch as a belt-and-braces guard for exotic loader behaviour; failing to recognise an assembly as "known empty" just falls through to the GetCustomAttributes path that already has its own try/catch. Reported on Marten today against the cold-start optimization changes. See https://aka.ms/GlobalizationInvariantMode.
This was referenced Apr 30, 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.
Problem
Assembly.GetName().Name, used by the cold-start prefilter inDiscoverGeneratedEvolvers, walksAssemblyName.GetLocale()→CultureInfo.GetCultureInfo(name)under the hood. Under globalization-invariant mode (<InvariantGlobalization>true</InvariantGlobalization>— implied by<PublishAot>true</PublishAot>) any culture-tagged satellite assembly (e.g.pt-br) makes that lookup throwCultureNotFoundException. The result for downstream consumers is a crash onDocumentStore..ctor(or the equivalent host-build entry point):Reported today against Marten's cold-start optimization changes.
Fix
Use
Assembly.FullNameand split on the first comma to get the simple name.FullNameis pre-cached on the runtime assembly and doesn't traverseCultureInfo. Wrap intry/catchas a belt-and-braces guard for exotic loader behaviour — failing to recognise an assembly as "known empty" just falls through to the existingGetCustomAttributespath that has its owntry/catch.Test plan
dotnet build src/JasperFx.Events/JasperFx.Events.csprojclean<InvariantGlobalization>true</InvariantGlobalization>plus a loaded satellite assembly, which is hard to wire up in a portable test rig — covered instead by the existing prefilter tests + this fix's defensive try/catch fallback. Will follow up if anyone has a clean way to harness the invariant-mode case.🤖 Generated with Claude Code