Release v20.60.3
Summary
A command that composes its own event source id could take the whole request down with it. ICanProvideEventSourceId.GetEventSourceId() builds the key from the command's own properties, so partial or hostile input leaves it composing a key that arrived null — in practice an implicit conversion on a generic EventSourceId<T>, which throws.
What makes this one sharp is where it happens. Command context values are built before the filter chain, so the throw escaped the per-filter handling that exists precisely to turn bad input into a clean response, and surfaced as an unhandled server error instead.
The reflection-based fallback already had the answer: EventSourceExtensions.GetEventSourceId resolves an uncomposable key to EventSourceId.Unspecified and documents exactly this reasoning. The provided-key branch was simply the one path that never got the same treatment. This aligns them.
Fixed
- A command implementing
ICanProvideEventSourceIdno longer returns an unhandled server error when its key cannot be composed from the incoming payload — an uncomposable or null key resolves toEventSourceId.Unspecified, so the command reaches the filter and validation stages that turn bad input into a proper response.
Behavior
| Command shape | Before | After |
|---|---|---|
| Provides a key successfully | that key | unchanged |
| Provides a key that throws while composing | unhandled server error | EventSourceId.Unspecified |
Provides a null key |
null context value, dereferenced downstream |
EventSourceId.Unspecified |
| Carries a key property (reflection fallback) | resolved from property | unchanged |
| Carries no key at all | fresh EventSourceId.New() |
unchanged |