Fix invalid generated class name for batched (array) message types (GH-3399)#3406
Merged
Conversation
…H-3399) The duplicate-TypeName disambiguation in HandlerGraph rebuilt the generated handler class name straight off the message type. For a batched message -- BatchMessagesOf<T>() makes T[] the handled message type -- that emitted a name like "ItemDeleted[]1177234954_TelemetryHandlerHandler550305999", which is not a legal C# identifier, so codegen died with CS1514/CS1513/CS1001 and took the app down at startup. Centralize the codegen-safe name composition that HandlerChain already did ad hoc (Replace("[]", "Array")) into HandlerChain.GeneratedTypeNameFor, add JasperFx's Sanitize() for any other punctuation, and use it on the disambiguation path in HandlerGraph. Reported by @outofrange-consulting. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This was referenced Jul 14, 2026
This was referenced Jul 18, 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.
Closes #3399. For 6.18.0. Reported by @outofrange-consulting — thank you, the repro was exact. (Supersedes #3405, which had the wrong commit pushed to its branch from a shared working tree; the fix itself is unchanged.)
Startup-fatal
HandlerGraph.cs:389-390composed the generated class name straight off the message type when disambiguating duplicateTypeNames:ToSuffixedTypeNamestrips generic arity but does nothing about arrays. SinceBatchMessagesOf<T>()makesT[]the handled message type, that emitted:— not a legal C# identifier →
CS1514/CS1513/CS1001→ the application dies at startup.Tellingly,
HandlerChain.cs:69/85andSagaChain.cs:166already guarded this with an ad-hoc.Replace("[]", "Array"). The disambiguation path was the one site that didn't.The trigger — and why our tests missed it
Two conditions were obvious. A third was not, and it is the reason this went unnoticed:
MultipleHandlerBehavior.Separated, andHandlerChain.cs:114gates sticky-chain creation ongrouping.Count() > 1. Without a second handler there are no sticky chains, so the disambiguation branch never runs — condition (3) is load-bearing. With it, the shared handler class gets two sticky chains both named off the handler type (HandlerChain.cs:85), theTypeNames collide, and the duplicate path fires.That pins the coverage gap exactly:
separated_batch_routing.csandbatching_with_separated_handlers.csdo exerciseSeparated+ batching, but every handler class in them handles exactly one message type — so stickyTypeNames never collide.Not a 6.17.x regression; the disambiguation path is old.
Fix
Centralized the scattered
.Replace("[]", "Array")idiom intoHandlerChain.GeneratedTypeNameFor(Type, string), reusing the existingJasperFx.Core.Reflection.Sanitize()helper rather than hand-rolling one, and applied it at the disambiguation site plus the three pre-existing sites that had each solved it locally.Collisions remain impossible:
ToSuffixedTypeNameappends a hash of the type's full name, andTvsT[]differ there. The test asserts distinctness, not merely that the name is legal.Verification
Compilation failures! CS1514/CS1513/CS1001, then green.CoreTests1923 passed, 0 failed (net9.0).wolverine.slnxRelease build: 0 warnings, 0 errors.🤖 Generated with Claude Code