fix(api): use f-string for raise messages in trigger debug event selectors

这个报错通常出现在 Dify 工作流使用「触发节点(Trigger Start)」做 Draft > Trigger > Run single node 调试时,后端 raise ValueError 用了 %s 占位符加多个位置参数,导致异常消息被渲染成 Python 元组字符串而不是可读文本。优

快速结论:这个报错通常出现在 Dify 工作流使用「触发节点(Trigger Start)」做 Draft > Trigger > Run single node 调试时,后端 raise ValueError 用了 %s 占位符加多个位置参数,导致异常消息被渲染成 Python 元组字符串而不是可读文本。优先排查 api/core/trigger/debug/event_selectors.py 中 create_event_poller 的 raise 写法。

适用环境:Issue 已确认环境为 Dify 1.15.0、Self Hosted (Docker);复现验证中还涉及 main 分支 commit 519ef8b 与版本 1.17.1,并针对运行中的 console API 测试。

最快修复方案:将 create_event_poller 中最后一处 raise ValueError("unable to create event poller for node type %s", node_type) 改成 f-string,并为该报错消息补充单元测试。该修复对应 PR #43851(Issue 中说明已提交,待维护者审核)。

注意事项:Issue 复现结论显示,四个站点中只有 create_event_poller 这一处能稳定触发元组消息;另外三处 Node data not found for node %s 在当前代码路径下可能不可达,Issue 中尚未就「改为 f-string / 删除死代码 / 改成 4xx」达成最终一致,未确认前不要一并大改。

问题场景

在自托管(Docker)Dify 中打开一个带 trigger start node 的工作流应用,进入 Draft > Trigger > Run single node 调试。当触发的节点类型无法创建 event poller(例如使用已存在的 Start 节点 id 调用 trigger run)时,接口返回 400,但返回的 message 不是格式化后的字符串,而是一个 Python 元组样式的文本。

Issue 复现者还在 main 分支与 1.17.1 的 console API 上对比了 4 个请求路径,结论是只有下面表格中的 D 能复现元组消息,A/B/C 返回通用 500 Internal Server Error。

报错原文

POST /apps//workflows/draft/trigger/run

400
{"code":"invalid_param","message":"('unable to create event poller for node type %s', 'start')"}

原因分析

最可能的原因是 Python 异常构造方式写错:raise ValueError("...%s...", var) 把 %s 占位符字符串和变量作为多个位置参数传给 Exception.__init__,Python 不会自动做 % 插值,因此 str(exception) 会显示为元组,形如 ('unable to create event poller for node type %s', 'start')。

正确写法应是 f-string 或先做字符串格式化,例如把消息内插成完整字符串。Issue 指出这是与 #37607 相同的 bug pattern(当时修复的是 resume_workflow_execution),而这次还发现另外几处同类写法,其中 Node data not found for node %s 的三处因为 Workflow.get_node_config_by_id 会先抛 NodeNotFoundError,在当前代码路径下可能不可达。

环境排查

  • 确认 Dify 版本:Issue 报告为 1.15.0;复现者还在 main(commit 519ef8b8c2d75f597b8a1dfff79ef4b8c5013e3e)和 1.17.1 上做过验证。
  • 确认部署方式:Self Hosted (Docker)。
  • 确认触发路径:POST /apps/<id>/workflows/draft/trigger/run,且传入的是已存在的 Start 节点 id。
  • 确认相关代码位置:api/core/trigger/debug/event_selectors.py 的 create_event_poller,以及 api/controllers/console/app/workflow.py。
  • Issue 未提供 Python、CUDA、PyTorch、显卡等环境证据,因此这些项不在本指南中作为排查前提。

解决步骤

  1. 定位 api/core/trigger/debug/event_selectors.py 中 create_event_poller 的最后一处 raise,即抛出 unable to create event poller for node type %s 的那一行。
  2. 将该 raise ValueError("unable to create event poller for node type %s", node_type) 改为使用 f-string 的单一消息字符串(Issue 对应 PR #43851 只针对这一处 case D)。
  3. 为该消息补一个单元测试,断言异常消息中已正确内插 node_type,而不是以元组形式出现。
  4. 对另外三处 Node data not found for node %s 暂不做机械修改,等待维护者明确处理方式(改为 f-string、删除死 guard,或让缺失节点返回 4xx 而非 500)。
  5. 如果使用旧版本且短期内不方便改代码,可优先避免使用不支持的 trigger 节点类型调用 trigger/run,因为该 400 元组消息正是从这一路径产生。

验证方法

重新对已存在的 Start 节点 id 调用 POST /apps/<id>/workflows/draft/trigger/run,确认返回的 invalid_param 消息已是完整可读字符串(node_type 已内插),而不再是 ('unable to create event poller for node type %s', 'start') 这种 Python 元组样式。若同时运行了新增单元测试,应看到针对该异常消息的断言通过。

参考来源

langgenius/dify #38476(含关联 PR #38478、#43851,以及同类修复 #37607 的上下文)

GamsGo AI

AI 工具推荐

想把多个 AI 模型放在一个入口?

GamsGo AI 集成 ChatGPT、DeepSeek、Gemini、Claude、Midjourney、Veo 等常用模型,适合写作、绘图、视频和日常 AI 工作流。

了解 GamsGo AI

推广链接:通过此链接购买,我可能获得佣金,不影响你的价格。

这个方案解决了吗?

celebrityanime
celebrityanime
文章: 28959

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注