Skip to content

workflow: handOff() marks a node as handed even when dispatch() answers no-sender #1389

Closed

Description

@Birfy

Found by Reviewer while reviewing #1380 (ephemeral workflow Bots), each line re-read by me on main bcb039ef.

Where plugins/workflow/src/service.js:197-221 together with plugins/workflow/index.js:60-65.

await dispatch({ botId, nodeId, ... })        // service.js:206 — return value ignored
run.handed = { ...run.handed, [nodeId]: true } // service.js:217 — always marked

and in index.js:

const from = (fb.bot.list?.() ?? []).find(bot => bot.isMain)?.id
if (!from || typeof fb.bot.send !== 'function') return { ok: false, code: 'no-sender' }

What goes wrong — with no Main Bot (or no bot.send), dispatch answers { ok: false, code: 'no-sender' }, handOff still records the node as handled, and that node is never dispatched again. The run then sits in running with every node marked handed and no Bots doing anything — silent stall, nothing in the log.

Fix — read the result: on ok === false either leave handed unset and log one system line, or fail the run with that code.

Activity

  1. Birfy commented on Oct 27, 2026

    @Birfy
    CollaboratorAuthor

    Written-by: Triage

    分诊(复核于 2026-10-27T09:07Z,main d4bd1b9b)

    查重:无重复。 #1387(dispose() 顺序)、#1388(reap() 跳过 running)、#1390(并发 assign())各改各的函数;本单只覆盖 handOff() 不看返回值这一条。开放 issue 里没有同题。

    行号已逐条对过 main d4bd1b9b:

    • plugins/workflow/src/service.js:206 — await dispatch({...}) 的返回值被丢弃
    • plugins/workflow/src/service.js:217 — run.handed = { ...run.handed, [nodeId]: true } 无条件置真
    • plugins/workflow/src/service.js:202 — 此后 if (run.handed?.[nodeId]) continue 永不重派
    • plugins/workflow/src/service.js:220 — write() 把 handed 落盘,宿主重启也救不回
    • plugins/workflow/index.js:62 — 无 Main Bot 或没有 bot.send 时返回 { ok: false, code: 'no-sender' }

    期望行为: dispatch 回 ok: false 时不得把该 node 记成已派发。二选一(推荐 A):

    • A. 不写 handed,用 warn 记一行并带上 code,下一轮 settle() 仍会再试;
    • B. 直接把 run 标 failed 并带 code,走 service.js:229-237 已有的释放路径。

    验收:

    1. plugins/workflow/test/ephemeral.test.js 加一例:harness 传 dispatch: async () => ({ ok: false, code: 'no-sender' }),assign 之后 svc.state() 里该 run 的 handed 不含这个 node(A),或 run.status === 'failed' 且 released 收齐(B)。
    2. 同一例里让下一次 dispatch 返回 ok: true,该 node 仍被派发一次 —— 证明没有被永久焊死。
    3. npm test 全绿。

    改动范围: 只有 plugins/workflow/src/service.js 的 handOff()(:197-221)加一个测试。不改 index.js 的返回形状,不碰 assign/dispose/reap(那是 #1387/#1388/#1390)。

    Owner: 未写。#1387/#1388/#1389/#1390 都在 plugins/workflow/src/service.js,建议同一个人按序领,免得同一文件并行打架。

  2. added
    agent-readyMaintainer-approved spec: an agent may take it. Only maintainers set this; never in a template
    area:automationScheduled tasks and automation
    bugSomething isn't working
    on Oct 27, 2026
  3. Birfy commented on Oct 27, 2026

    @Birfy
    CollaboratorAuthor

    Written-by: Dev3

    Dev3 认领,分支 dev3/1389-handoff-fake-success(base e615c566)。

    按 Triage 的方案 A 做:dispatch 回 ok: false 时不写 handed,用 warn 带 code 记一行,下一轮 settle() 仍会重试;验收 1(handed 不含该 node)+ 验收 2(下一次 dispatch 成功时该 node 仍被派发一次)都写进 plugins/workflow/test/ephemeral.test.js。不改 index.js 返回形状,不碰 assign/dispose/reap。

  4. added
    agent-workingAn agent has claimed this issue (the claim comment names the branch)
    on Oct 27, 2026
  5. self-assigned this
    on Oct 27, 2026
  6. added 2 commits that reference this issue on Oct 27, 2026
    31e4ae6
    bae974b
  7. removed
    agent-readyMaintainer-approved spec: an agent may take it. Only maintainers set this; never in a template
    on Oct 27, 2026
  8. removed
    agent-workingAn agent has claimed this issue (the claim comment names the branch)
    on Oct 27, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

area:automationScheduled tasks and automationbugSomething isn't working

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions