Skip to content

Fix #2595: explicit DeliveryOptions.SagaId on saga Start cascades should win#2597

Merged
jeremydmiller merged 1 commit intomainfrom
investigation/2595-saga-start-explicit-sagaid
Apr 27, 2026
Merged

Fix #2595: explicit DeliveryOptions.SagaId on saga Start cascades should win#2597
jeremydmiller merged 1 commit intomainfrom
investigation/2595-saga-start-explicit-sagaid

Conversation

@jeremydmiller
Copy link
Copy Markdown
Member

Summary

  • Closes Saga Start cascades silently drop explicit DeliveryOptions.SagaId #2595
  • When a saga's Start cascaded a message tagged with an explicit DeliveryOptions { SagaId = ... }, the explicit value was silently overwritten by the inbound envelope's SagaId (or the context's _sagaId). A downstream reply that auto-propagated envelope.SagaId then routed to the wrong saga and failed with UnknownSagaException.
  • One-line precedence reorder in MessageContext.TrackEnvelopeCorrelation so that an explicit SagaId already set on the outbound envelope (e.g. from DeliveryOptions.Override, which runs first) wins over the context default. Falls through to the previous chain (_sagaId → inbound Envelope.SagaId) when no explicit value was set.

Notes

  • The fix also covers replies: RespondToSenderAsync(reply, new DeliveryOptions { SagaId = ... }) had the same bug — the explicit value was clobbered. Same precedence reorder fixes both.
  • Default behavior (no explicit DeliveryOptions.SagaId, just inherit-from-context) is byte-for-byte identical to today, so the existing saga compliance suites pass unchanged.

Test plan

  • New repro Bug_2595_explicit_delivery_options_sagaid_should_win (Marten + saga Start cascade with explicit DeliveryOptions.SagaId) — fails on main, passes with fix
  • dotnet test src/Testing/CoreTests — 1360/1360 pass
  • dotnet test src/Persistence/MartenTests --filter "Saga|saga|Bug_310|Bug_756|Bug_2595" — 65/65 pass

🤖 Generated with Claude Code

Fixes #2595. When a saga's static `Start` method generated its own saga
id inside the method body and cascaded a message tagged with an explicit
`DeliveryOptions { SagaId = ... }`, Wolverine silently overwrote that
explicit value with the inbound envelope's `SagaId`. A downstream reply
that auto-propagated `envelope.SagaId` then routed to the wrong saga and
failed with `UnknownSagaException`.

Root cause: `MessageContext.TrackEnvelopeCorrelation` ran *after*
`DeliveryOptions.Override` had already stamped the explicit `SagaId` on
the outbound envelope, and unconditionally clobbered it with the
context's `_sagaId` (which was sourced from the inbound envelope).

Fix: reorder the precedence so an explicit `SagaId` on the outbound
envelope wins. The fallback chain (`_sagaId` → inbound `Envelope.SagaId`)
is preserved unchanged for the default "inherit from context" case, so
existing saga compliance tests are unaffected. Also fixes the analogous
case for replies (`RespondToSenderAsync(reply, new DeliveryOptions
{ SagaId = ... })`) which exercised the same code path.

Co-Authored-By: Claude Opus 4.7 (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.

Saga Start cascades silently drop explicit DeliveryOptions.SagaId

1 participant