快速结论:该报错通常出现在使用 Webhook Trigger 上传文件、并异步执行工作流的场景中:Webhook 上传的 ToolFile 记录归属于 Webhook 创建者账号(Account ID),而异步执行时按 Trigger EndUser ID 做文件归属过滤,导致下游节点读取不到该文件。优先排查 Webhook 上传文件与执行用户之间的归属不一致问题。
适用环境:Dify 1.17.1;Self Hosted(Docker);工作流使用 Webhook Trigger,并包含单个文件参数(multipart/form-data),异步执行。
最快修复方案:暂无确认的一步修复方案。Issue 中报告者通过本地修改,将 ToolFile.user_id 设为 Trigger EndUser ID 后,同一工作流可以完成;这属于本地验证,未合入上游,不能视为正式修复。
注意事项:直接修改文件归属逻辑会影响文件访问控制模型;Issue 中建议的正式修复方向是:在 _create_file_from_binary() 中提前解析或创建 Trigger EndUser,或参照 PR #41300 的执行内授权机制(grant_tool_file_access)显式授权该文件 ID。两者均需回归测试,未验证前不要在生产环境直接套用。
问题场景
在 Dify 1.17.1(Self Hosted / Docker)中创建一个含 Webhook Trigger 的工作流:触发器接收一个字符串字段和一个文件字段(示例为 chat_history_file),通过 multipart/form-data 上传。文件字段连接到 Document Extractor 或邮件附件等下游节点,并以异步方式执行工作流。Webhook 端点返回 HTTP 200,但异步工作流失败。
报错原文
ToolFile <id> not found
Failed to build FileVariable for webhook file parameter chat_history_file
Variable ['<node-id>', 'chat_history_file'] is not an ArrayFileSegment
原因分析
根据 Issue 及维护者回复的分析,根因是文件归属与执行用户不一致:
WebhookService._create_file_from_binary()创建ToolFile时使用user_id=webhook_trigger.created_by,即工作流/Webhook 所有者的 Account ID。trigger_workflow_execution()执行工作流时使用通过get_or_create_end_user_by_type(type=EndUserType.TRIGGER, ..., user_id=None)得到的独立 TriggerEndUser,该 EndUser 的 ID 成为WorkflowTriggerLog.created_by。- 异步任务按该 ID 重建执行用户,
BaseAppGenerator._bind_file_access_scope()为其绑定FileAccessScope,并开启requires_user_ownership = True。 DatabaseFileAccessController.apply_tool_file_filters()在此作用域下只允许查找ToolFile.user_id == scope.user_id的记录(或位于本次执行granted_tool_file_ids白名单中的文件)。Webhook 上传的文件携带的是 Account ID,也不在授权集合中,因此抛出ToolFile <id> not found,并导致后续节点变量段类型不匹配。
PR #41300 曾为“工作流作为工具”场景中工具产出的文件添加执行内授权(grant_tool_file_access),但 Webhook 上传发生在同步请求阶段,早于执行,未触发该授权机制,因此不覆盖此场景。这是基于 Issue 讨论的原因判断。
环境排查
- 确认 Dify 版本是否为 1.17.1 或相近版本,并记录升级前后是否仍复现。
- 确认部署形态:Self Hosted(Docker),排查 worker(Celery 异步任务)日志,检索
ToolFile、Failed to build FileVariable等关键字。 - 确认 Webhook Trigger 配置:文件参数是否为单文件字段、请求是否为
multipart/form-data。 - 确认工作流是否以异步方式触发,并检查
WorkflowTriggerLog.created_by对应的 EndUser 类型是否为 TRIGGER。 - 检查该
ToolFile记录的user_id,确认其对应 Account ID 而非 Trigger EndUser ID。 - 如同时遇到“缺少文件参数时回退到整个 files 映射”的现象,注意 Issue 提到的另一个问题 #41071,可能与本次测试相互干扰。
解决步骤
- 先复现并定位:用 curl 向 Webhook 发送带文件字段的
multipart/form-data请求,确认返回 HTTP 200,同时检查 worker 日志中是否出现上述两条文件相关报错。 - 在数据库中核对该
ToolFile的user_id与WorkflowTriggerLog.created_by是否指向不同用户(Account ID 与 Trigger EndUser ID)。 - 如需本地验证,可优先尝试:在
_create_file_from_binary()中改用本次执行对应的 Trigger EndUser ID 创建ToolFile;报告者以此方式验证同一工作流可成功完成。该方式仅为本地测试结论,非上游修复。 - 如采用代码侧修复,按 Issue 建议方向二选一:在创建
ToolFile之前解析或创建 Trigger EndUser;或参照 PR #41300 的模式,将上传文件 ID 显式加入执行作用域的授权集合。 - 在修改后的环境中重新发送同样的 curl 请求,观察异步执行是否完整走完。
验证方法
重新触发一次相同的 Webhook 上传请求,确认:Webhook 返回 HTTP 200;worker 日志中不再出现 ToolFile <id> not found 与 Failed to build FileVariable for webhook file parameter chat_history_file;下游节点能正常获取文件,且不再报 Variable ['<node-id>', 'chat_history_file'] is not an ArrayFileSegment;异步工作流执行状态为成功。
参考来源
AI 工具推荐
想把多个 AI 模型放在一个入口?
GamsGo AI 集成 ChatGPT、DeepSeek、Gemini、Claude、Midjourney、Veo 等常用模型,适合写作、绘图、视频和日常 AI 工作流。
推广链接:通过此链接购买,我可能获得佣金,不影响你的价格。
这个方案解决了吗?
可以继续搜索完整报错,或查看同一工具的其他排查指南。


