Skip to content

Local world re-enqueues parked interactive sessions into an unhandled queue on restart #715

Closed

Description

@Volpestyle

Eve version

0.22.4

Problem

Restarting a built eve start application with a normal interactive session parked at session.waiting logs:

[world-local] Re-enqueued 1 active run(s) on startup
[world-local] Queue message failed (attempt 1, HTTP 400) {
  queueName: '__wkf_workflow_workflow//eve//workflowEntry',
  handlerError: '{"error":"Unhandled queue"}'
}

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

  1. eve build, then eve start with a persistent WORKFLOW_LOCAL_DATA_DIR.
  2. Create an interactive session, complete turn 1, and wait for session.waiting.
  3. Stop the server cleanly.
  4. Restart eve start with the same built output and data directory.
  5. Observe the local world re-enqueue the parked root run to a queue namespace the restarted handler rejects with HTTP 400 Unhandled queue.
  6. 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.

Activity

  1. asdiamond commented on Jul 12, 2026

    @asdiamond

    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):

    await enqueue(`__wkf_workflow_${run.workflowName}`, { runId: run.runId })

    The handler rejects anything that fails queueName.startsWith(prefix), and

    "__wkf_workflow_workflow//eve//workflowEntry".startsWith("__eve657665_wkf_workflow_") // false, always
    

    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():

    1. Any eve app on 0.22.5, next dev (or eve start with a persistent data dir)
    2. Create a session, complete a turn, let it park at session.waiting
    3. Restart the process
    4. [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:

    await enqueue(`${queuePrefix("workflow", envNamespace())}${run.workflowName}`, { runId: run.runId })

    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.

  2. asdiamond commented on Jul 12, 2026

    @asdiamond

    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).

  3. ruiconti commented on Jul 13, 2026

    @ruiconti
    Contributor

    Thanks for reporting. This has been fixed on 0.22.6.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't workingcorep2

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions