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
Local world re-enqueues parked interactive sessions into an unhandled queue on restart #715
The stale delivery continues retrying even though the client can explicitly continue the same session with its sessionId and continuationToken. In an isolated black-box test, turn 2 succeeded on the same session, replay was exact-once, and no user-visible failure occurred; the startup requeue remained as repeated retry noise/work.
Reproduction
eve build, then eve start with a persistent WORKFLOW_LOCAL_DATA_DIR.
Create an interactive session, complete turn 1, and wait for session.waiting.
Stop the server cleanly.
Restart eve start with the same built output and data directory.
Observe the local world re-enqueue the parked root run to a queue namespace the restarted handler rejects with HTTP 400 Unhandled queue.
Explicitly continue through the public session route; continuation still succeeds while the stale delivery retries.
Expected
A root interactive workflow parked for the next user message is not startup-requeued as runnable work, or its queue name is accepted by the restarted handler. Normal parked sessions should not create an indefinite 5-second retry loop or high-volume error logs after every process restart.
We hit the same behavior on 0.22.5 under next dev via withEve() (macOS, Node 24) and dug into the bundled Workflow runtime. It's a queue-namespace mismatch between eve's handler registration and the local world's startup re-enqueue:
Root cause
Handler side (namespaced). At boot, eve installs an agent-scoped Workflow queue namespace — WORKFLOW_QUEUE_NAMESPACE = "eve" + hex(agentName) (dist/src/internal/workflow/queue-namespace.js, installed from internal/nitro/host/configure-nitro-routes.js). The workflow queue handler is registered through @workflow/core's namespace-aware prefix builder, which produces __${namespace}_wkf_workflow_ when a namespace is set. For the default agent name eve that's:
__eve657665_wkf_workflow_
Startup re-enqueue side (un-namespaced). The local world's startup recovery lists pending/running runs and re-enqueues each with a hardcoded prefix, ignoring WORKFLOW_QUEUE_NAMESPACE (in the bundled @workflow chunk):
so every re-enqueued message gets HTTP 400 {"error":"Unhandled queue"}. Since world-local retries rejected deliveries with no attempt cap or dead-letter, each parked run becomes a permanent ~5s retry loop after every restart — and the loops accumulate with each additional parked session (and each Nitro worker reload in eve dev, e.g. on an .env.local change).
Live enqueues go through the namespace-aware builder (it reads WORKFLOW_QUEUE_NAMESPACE from the env), which is why everything else works.
Confirming the sessions themselves are fine
We verified what you observed: after a restart, POSTing a follow-up with the saved continuationToken resumes the same session with full model context (asked the model to recall a fact from turn 1 pre-restart; it did). The spam is purely the startup re-enqueue targeting a queue name that cannot match; the hook-resume delivery path is namespaced correctly.
Repro
Same as the OP's, and it also reproduces under next dev + withEve():
Any eve app on 0.22.5, next dev (or eve start with a persistent data dir)
Create a session, complete a turn, let it park at session.waiting
Restart the process
[world-local] Re-enqueued 1 active run(s) on startup → endless Queue message failed (attempt N, HTTP 400) … Unhandled queue
Suggested fix
Build the startup re-enqueue queue name with the same namespace-aware helper used for live enqueues, i.e. effectively:
Alternatively (or additionally): skip startup re-enqueue for runs parked on a hook wait — they're woken by hook resume, not queue delivery, so requeueing them as runnable work is wrong even with a matching namespace — and cap retries for Unhandled queue rejections so a mismatch can't become an unbounded loop.
The change lives in the vendored @workflow world packages (5.0.0-beta.30 line), so it may really belong upstream in the Workflow SDK — but since eve pins and bundles it, flagging it here first.
Happy to send a PR for whichever direction you'd prefer — the fix looks contained to the re-enqueue helper.
Opened a fix upstream in the Workflow SDK (the bug lives in @workflow/world's startup recovery, which eve bundles): vercel/workflow#2885
It builds the recovery queue name with the same namespace-aware helpers live enqueues use, so recovered runs target the queues the handler actually registers. Until it lands and eve picks up the new @workflow release, the noise can be silenced in dev by clearing .workflow-data before starting the server (at the cost of cross-restart resume, which otherwise works fine despite the spam).
Activity
asdiamond commentedon Jul 12, 2026
We hit the same behavior on 0.22.5 under
next devviawithEve()(macOS, Node 24) and dug into the bundled Workflow runtime. It's a queue-namespace mismatch between eve's handler registration and the local world's startup re-enqueue:Root cause
Handler side (namespaced). At boot, eve installs an agent-scoped Workflow queue namespace —
WORKFLOW_QUEUE_NAMESPACE = "eve" + hex(agentName)(dist/src/internal/workflow/queue-namespace.js, installed frominternal/nitro/host/configure-nitro-routes.js). The workflow queue handler is registered through@workflow/core's namespace-aware prefix builder, which produces__${namespace}_wkf_workflow_when a namespace is set. For the default agent nameevethat's:Startup re-enqueue side (un-namespaced). The local world's startup recovery lists
pending/runningruns and re-enqueues each with a hardcoded prefix, ignoringWORKFLOW_QUEUE_NAMESPACE(in the bundled@workflowchunk):The handler rejects anything that fails
queueName.startsWith(prefix), andso every re-enqueued message gets HTTP 400
{"error":"Unhandled queue"}. Since world-local retries rejected deliveries with no attempt cap or dead-letter, each parked run becomes a permanent ~5s retry loop after every restart — and the loops accumulate with each additional parked session (and each Nitro worker reload ineve dev, e.g. on an.env.localchange).Live enqueues go through the namespace-aware builder (it reads
WORKFLOW_QUEUE_NAMESPACEfrom the env), which is why everything else works.Confirming the sessions themselves are fine
We verified what you observed: after a restart, POSTing a follow-up with the saved
continuationTokenresumes the same session with full model context (asked the model to recall a fact from turn 1 pre-restart; it did). The spam is purely the startup re-enqueue targeting a queue name that cannot match; the hook-resume delivery path is namespaced correctly.Repro
Same as the OP's, and it also reproduces under
next dev+withEve():next dev(oreve startwith a persistent data dir)session.waiting[world-local] Re-enqueued 1 active run(s) on startup→ endlessQueue message failed (attempt N, HTTP 400) … Unhandled queueSuggested fix
Build the startup re-enqueue queue name with the same namespace-aware helper used for live enqueues, i.e. effectively:
Alternatively (or additionally): skip startup re-enqueue for runs parked on a hook wait — they're woken by hook resume, not queue delivery, so requeueing them as runnable work is wrong even with a matching namespace — and cap retries for
Unhandled queuerejections so a mismatch can't become an unbounded loop.The change lives in the vendored
@workflowworld packages (5.0.0-beta.30 line), so it may really belong upstream in the Workflow SDK — but since eve pins and bundles it, flagging it here first.Happy to send a PR for whichever direction you'd prefer — the fix looks contained to the re-enqueue helper.
asdiamond commentedon Jul 12, 2026
Opened a fix upstream in the Workflow SDK (the bug lives in
@workflow/world's startup recovery, which eve bundles): vercel/workflow#2885It builds the recovery queue name with the same namespace-aware helpers live enqueues use, so recovered runs target the queues the handler actually registers. Until it lands and eve picks up the new
@workflowrelease, the noise can be silenced in dev by clearing.workflow-databefore starting the server (at the cost of cross-restart resume, which otherwise works fine despite the spam).ruiconti commentedon Jul 13, 2026
Thanks for reporting. This has been fixed on 0.22.6.