You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Claim-check [Blob] properties are off-loaded but not re-hydrated on a local queue #3047
When a [Blob]-marked message is delivered via an in-process (durable) local queue, the claim-check serializer's Write off-loads the payload and nulls the property on the in-memory message (ClaimCheckMessageSerializer → accessor.Clear(message)), but the receive path reuses that same object and skips deserialization (HandlerPipeline: if (envelope.Message == null) is false), so ReadFromData/LoadBlobsAsync never re-hydrate. The handler receives a null payload.
It works correctly across a real transport (Rabbit/TCP/etc.) because that path forces a serialize→deserialize round-trip. Local delivery does not.
Mechanism
A durable local queue serializes the envelope on store (DurableLocalQueue.writeMessageData → Serializer.Write(envelope)), which fires the claim-check off-load + Clear(message) against the live in-memory message.
The durable queue then re-enqueues that sameEnvelope instance to its receiver.
In HandlerPipeline.executeAsync, envelope.Message is not null (it's the cleared object), so the deserialize branch — the only place LoadBlobsAsync re-hydrates — never runs.
A buffered (in-memory) local queue does not reproduce this: it never serializes on the local hand-off, so the off-load never fires. InvokeMessageAndWaitAsync also doesn't reproduce it (the handler runs inline, bypassing store-and-forward).
Expected
Local delivery should either not off-load, or off-load and re-hydrate symmetrically — the handler should always see the original payload.
Repro
Single host, UseClaimCheck(c => c.UseFileSystem(...)), Policies.UseDurableLocalQueues(), a local handler for a [Blob] message, SendMessageAndWaitAsync — the handler's blob property comes back null instead of the sent value.
Note
EncryptingMessageSerializer (the sibling serializer-decorator) does not mutate the in-memory message and is unaffected; claim-check's in-place Clear(message) is the root of the asymmetry. A fix should keep the serializer from leaving the live message mutated, matching the encryption precedent.
Activity