Skip to content

bug: parallel/pipeline 会吞掉取消异常并将已终止工作流标记为 completed #1345

Description

@ai-yang

问题概述

用户停止 workflow 后,agent() 抛出的 WorkflowAbortedError 会被 parallel()pipeline() 的通用 catch 当作普通任务失败处理并转换成 null。控制流异常没有传播到 runWorkflow(),最终运行记录和 run_done 事件都错误地写成 completed

严重度

严重(High)

  • 用户明确取消后,UI、事件流和持久化状态仍显示“已完成”。
  • 不完整结果以 [null] 的成功返回值进入下游,可能触发后续自动化。
  • 审计、恢复和完成通知都基于错误的终态。

环境

  • 代码版本:3bb6b5746238c418138eb96d57765d79012edd96
  • Bun:1.3.13
  • 系统:Linux 5.15.0-186-generic x86_64

稳定复现

使用预先 abort 的 AbortSignal 分别运行以下脚本(其余参数可复用 packages/workflow-engine/src/__tests__/runWorkflow.test.ts 的测试 ports):

const scripts = {
  direct: `return agent('x')`,
  parallel: `return parallel([() => agent('x')])`,
  pipeline: `return pipeline(['x'], (_prev, item) => agent(item))`,
}

const ac = new AbortController()
ac.abort()

const result = await runWorkflow({
  script: scripts.parallel,
  signal: ac.signal,
  // runId / ports / host / cwd / budgetTotal 使用正常测试值
})

在同一进程内重复运行可稳定得到:

direct   result={"status":"killed"}
         run_done={"status":"killed"}

parallel warning="parallel thunk #0 failed: workflow has been aborted"
         result={"status":"completed","returnValue":[null]}
         run_done={"status":"completed","returnValue":[null]}

pipeline warning="pipeline item #0 failed: workflow has been aborted"
         result={"status":"completed","returnValue":[null]}
         run_done={"status":"completed","returnValue":[null]}

实际行为

直接调用 agent() 时状态为 killed;只要相同调用包进 parallel()pipeline(),状态就变为 completed

预期行为

WorkflowAbortedError 是整个运行的取消控制流,应穿透组合器并由 runWorkflow() 映射为 killed。普通业务异常仍可保持当前的“记录 warning 并返回 null”契约。

根因

packages/workflow-engine/src/engine/hooks.ts 中:

  • parallel() 捕获每个 thunk 的全部异常并返回 null
  • pipeline() 捕获每条 pipeline 的全部异常并返回 null

两处都没有排除 WorkflowAbortedError。而 packages/workflow-engine/src/engine/runWorkflow.ts 只有在该异常传播出来时,才会产生 status: 'killed'

建议修复

在两处 catch 的最前面加入:

if (e instanceof WorkflowAbortedError) throw e

并补充两层回归测试:

  1. hooks 单元测试断言 parallel / pipeline 会重新抛出取消异常;
  2. runWorkflow 测试断言 result 与最终 run_done 均为 killed,同时保留普通异常转 null 的既有测试。

查重

已检索开放/关闭 issue 和全部 PR,关键词包括 WorkflowAbortedErrorparallel abortpipeline abortworkflow killed completed,未发现同因问题。

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions