-
Notifications
You must be signed in to change notification settings - Fork 304
Description
Bug Description
When using namespaces with the Hatchet TypeScript SDK, events.push() auto-namespaces event keys via applyNamespace(), but ctx.waitFor() in durable tasks does not apply the namespace to the eventKey condition. This causes a mismatch where pushed events can never be matched by waiting workflows.
Reproduction
-
Initialize Hatchet client with a namespace:
const hatchet = HatchetClient.init({ token, namespace: 'myapp' })
-
Create a durable task that waits for an event:
const task = hatchet.durableTask({ name: 'my-task', fn: async (input, ctx) => { const result = await ctx.waitFor( Or({ eventKey: 'my-event' }, { sleepFor: '30m' }) ) // Never receives the event }, })
-
Push an event from another part of the application:
await hatchet.events.push('my-event', { data: 'hello' })
Expected Behavior
The workflow should receive the event. Both events.push() and ctx.waitFor() should handle namespacing consistently — either both apply the namespace or neither does.
Actual Behavior
events.push('my-event', ...)sends the event asmyapp_my-event(namespaced viaapplyNamespace()inevent-client.js:38)ctx.waitFor(Or({ eventKey: 'my-event' }, ...))registers a wait formy-event(NOT namespaced —conditionsToPb()intransformer.jspasseseventKeydirectly without callingapplyNamespace())- The event key
myapp_my-eventnever matches the wait conditionmy-event, so the workflow times out
Root Cause
In v1/conditions/transformer.js, the conditionsToPb() function passes condition.eventKey directly to userEventKey without calling applyNamespace():
// transformer.js line ~30
userEventConditions.push({
base: { ...baseToPb(condition.base), expression: condition.expression || '' },
userEventKey: condition.eventKey, // <-- NOT namespaced
});Meanwhile, event-client.js always namespaces in push():
// event-client.js line ~38
push(type, input, options = {}) {
const namespacedType = applyNamespace(type, this.config.namespace);
// ...
}Workaround
Manually apply the namespace to the event key before passing it to waitFor():
function applyNamespace(eventKey: string): string {
const raw = process.env.HATCHET_NAMESPACE
if (!raw) return eventKey
const ns = raw.toLowerCase() + (raw.endsWith('_') ? '' : '_')
return eventKey.startsWith(ns) ? eventKey : `${ns}${eventKey}`
}
// In workflow:
const eventKey = applyNamespace(`agent:${sessionId}:message`)
await ctx.waitFor(Or({ eventKey }, { sleepFor: '30m' }))Environment
- SDK version:
@hatchet-dev/typescript-sdk@1.10.8 - Node.js: v22
- Using Hatchet Cloud
Impact
This completely breaks durable event-driven workflows when namespaces are used. Without the workaround, subsequent messages to running workflows are silently lost.