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
[Bug] set_dynamic_signal_handler delivers buffered signals grouped by name instead of in arrival order #1996
A cart workflow loads its state with an activity, then registers a dynamic signal handler with workflow.set_dynamic_signal_handler and routes events like add, clear and checkout by signal name. The client starts the workflow and sends the shopper's events right away, while the load activity is still running.
Describe the bug
Signals that arrive before the dynamic handler is set are buffered. When the handler is set, they are delivered grouped by signal name, in the order each name was first seen, not in the order they arrived. For add apple, clear, add pear, checkout, the handler sees add apple, add pear, clear, checkout, so the cart is empty at checkout instead of holding pear.
Nothing fails and nothing is logged. The workflow just computes a different state from the signals in its history. The same happens when the signals arrive before the first workflow task (sent right after start while workers are busy) and the handler is set at the top of run.
A named handler set with workflow.set_signal_handler only takes its own signals, so their order is kept. A @workflow.signal(dynamic=True) method gets the same signals in arrival order, because nothing is buffered for it.
The TypeScript SDK keeps one bufferedSignals array and a default signal handler drains it in order (dispatchBufferedSignals). The .NET SDK keeps one list and applies all of it in order when DynamicSignal is set (DynamicSignal).
Changing the order changes replay for histories that already went through this path, so a fix needs a workflow logic flag.
For prioritization purposes, can you speak to how this impacts you? Was this something you actually encountered, and is there a reason setting the dynamic handler earlier, or using a static one, is not an option?
I didn't run into it in an app. I found it reading the signal buffering code and reproduced it with a real worker. A static @workflow.signal(dynamic=True) method keeps the order, so that works as a workaround. Setting the handler earlier doesn't fully avoid it, though: even from __init__, signals that arrive with the first workflow task are still grouped by name.
Activity
tconley1428 commentedon Oct 21, 2026
For prioritization purposes, can you speak to how this impacts you? Was this something you actually encountered, and is there a reason setting the dynamic handler earlier, or using a static one, is not an option?
RachelWanggg commentedon Oct 21, 2026
I didn't run into it in an app. I found it reading the signal buffering code and reproduced it with a real worker. A static
@workflow.signal(dynamic=True)method keeps the order, so that works as a workaround. Setting the handler earlier doesn't fully avoid it, though: even from__init__, signals that arrive with the first workflow task are still grouped by name.tconley1428 commentedon Oct 21, 2026
I'm inclined not to fix this since it is niche with no known impact. If anyone hits it please reopen.