Dify 两轮对话均带附件为何报 Unsupported chat content part?

👁 83 次阅读

Dify 两轮对话均带附件为何报 Unsupported chat content part?

问题来源:https://github.com/langgenius/dify/issues/41059

现象描述

在 langgenius/dify 仓库的 issue #41059 中,用户报告了一个连续两轮对话携带附件时触发的报错。该 issue 当前状态为 open,标签为 🐞 bug 与 review: low,创建于 2026-08-21,最后更新同为 2026-08-21。剔除机器人留言与无效回复后,实质讨论共 3 条。反应合计为 0,说明该问题目前社区关注度不高。 复现路径为:第一轮对话包含附件,第二轮对话同样包含附件,此时请求失败。用户使用的 Dify 版本为 1.16.1,部署方式为 Self Hosted (Docker),接入的大模型为 Qwen 3.8-27B-FP8。 期望行为是:在分析第二轮文件的同时,正常保留第一轮附件的记忆。 实际行为是返回如下错误:
{
  "text": "处理失败!",
  "error_message": "req_id: 28798a2a82 PluginInvokeError: {\"args\":{\"description\":\"[models] Error: API request failed with status code 400: {\\\"error\\\":{\\\"message\\\":\\\"Unsupported chat content part type: 'file'. Supported types: audio_embeds, audio_url, image_embeds, image_pil, image_url, input_audio, input_image, input_text, output_text, prompt_embeds, refusal, text, thinking, tool_reference, video_url. (parameter=type, value=file)\\\",\\\"type\\\":\\\"BadRequestError\\\",\\\"param\\\":\\\"type\\\",\\\"code\\\":400}}\"},\"error_type\":\"InvokeError\",\"message\":\"[models] Error: API request failed with status code 400: {\\\"error\\\":{\\\"message\\\":\\\"Unsupported chat content part type: 'file'. Supported types: audio_embeds, audio_url, image_embeds, image_pil, image_url, input_audio, input_image, input_text, output_text, prompt_embeds, refusal, text, thinking, tool_reference, video_url. (parameter=type, value=file)\\\",\\\"type\\\":\\\"BadRequestError\\\",\\\"param\\\":\\\"type\\\",\\\"code\\\":400}}\"}",
  "error_type": "PluginInvokeError"
}
错误的关键信息集中在后端返回的 400 报文:Unsupported chat content part type: 'file'. Supported types: audio_embeds, audio_url, image_embeds, image_pil, image_url, input_audio, input_image, input_text, output_text, prompt_embeds, refusal, text, thinking, tool_reference, video_url. (parameter=type, value=file)。后端明确列出了它接受的 content part 类型清单,file 并不在其中。

背景原因

从报错文本可以读出问题的大致轮廓:请求在到达模型服务端时,对话消息里携带了一个 content part,其 type 字段的值为 file;而后端接受的类型清单中并不存在 file 这一项,因此直接以 HTTP 400 拒绝了整个请求。 据 issue 讨论,Dify 的记忆功能工作原理是把此前的对话轮次作为 prompt messages 重放给模型。当第一轮携带附件时,该附件在历史中被记录为一个 content part;第二轮再次携带附件并开启记忆时,历史中的这个附件 content part 会被一并送回模型服务端。若该模型实体并未声明支持这一类内容类型,服务端便返回上述 400 错误。 社区成员 engmohamedsalah 在 2026-08-24 的评论中给出了对该机制的判断,并说明已经提交了修复 PR #41192。据这条评论,修复思路是:在历史重放阶段,把每个附件 part 依据模型声明的特性(AIModelEntity.supports_prompt_content_type)进行判定,对不支持的类型降级为一段文本说明,从而让较早的轮次保留上下文,而不是让整个请求以 400 Unsupported chat content part type 失败。该评论同时声明当前轮次的文件不受此改动影响,并已补充单元测试。 需要明确的是,上述修复来自社区贡献者的 PR,不代表官方已确认或合入。issue 当前仍为 open 状态,标签中的 review: low 说明其评审优先级被标记为低。截至末条实质评论,官方侧未给出复现确认或修复版本号。因此该问题的处理状态是:官方尚未合入方案。

排查或量化方法

由于实质评论仅 3 条,且其中一条为提问、一条为回答(围绕关闭对话记忆的操作展开),可用的定位信息主要来自报错报文本身。以下为可依据现有信息进行的判断方法。 确认报错来源层级。 错误类型为 PluginInvokeError,内层描述为 [models] Error: API request failed with status code 400。这说明失败发生在模型调用插件向模型服务端发起请求之后,由服务端返回 400,而非 Dify 自身的解析阶段。定位时应先看模型服务端的返回报文,而不是查 Dify 的节点配置。 确认触发条件是历史重放,而非当前轮。 依据社区评论的判断,当前轮的文件不受该机制影响,问题出在历史轮次的附件以 content part 形式被重放。可对照的验证方式是:仅第二轮携带附件、第一轮不带附件时是否仍然报错;或第一轮带附件、第二轮不带附件时是否仍然报错。据 issue 讨论,该判断认为问题只在两轮都带附件时出现。需要说明的是,该验证思路来自 issue 讨论的推断,issue 中未提供实际验证记录。 对照后端支持类型清单。 报错报文已经给出服务端接受的类型全集,可作为比对基线:
服务端声明支持的类型是否包含 file
audio_embeds否
audio_url否
image_embeds否
image_pil否
image_url否
input_audio否
input_image否
input_text否
output_text否
prompt_embeds否
refusal否
text否
thinking否
tool_reference否
video_url否
file不在清单中
这张表的作用是:当出现同类 400 报文时,可直接比对 value= 后面的类型名是否落在服务端清单内,从而判断是类型不被支持,而非参数格式或鉴权问题。 关于历史重放本身的开关。 issue 讨论中出现了关闭对话记忆的建议,提问者追问「How to operate specifically: Disable conversation memory?」。社区回复给出的操作路径针对 Chatflow 应用:在 Studio 中打开对应 Chatflow,点击需要修改的 LLM 节点,在右侧配置面板找到 Memory 区域,将 Memory 关闭,或把记忆窗口大小设为 0。该回复同时说明,记忆功能的工作方式是把此前的对话轮次作为 prompt messages 重放。需要说明的是,这条回复在事实记录中被截断,后续内容未完整保留,因此不宜据此推断更多配置细节。

当前处理路径与局限

由于实质评论仅有 3 条,官方侧尚无实质回应,本节只归纳 issue 中已经出现过的动作与建议,不额外补充未经讨论的排查步骤。 路径一:关闭对话记忆。 这是 issue 讨论中给出的直接规避方式。针对 Chatflow 应用,操作位置为 Studio 中的 LLM 节点,在右侧配置面板的 Memory 区域关闭 Memory,或将记忆窗口大小设为 0。该方式的局限很明确:关闭记忆意味着模型不再接收此前轮次的上下文,跨轮次引用第一轮附件内容的能力随之丧失,这与 issue 中「Normally, remember the attachments of the first round while analyzing the files of the second round」的期望行为正好相反。它属于回避问题,而非解决问题。 路径二:等待社区 PR 的评审结果。 社区成员 engmohamedsalah 在评论中说明已提交修复 PR #41192,思路是对历史重放中的附件 part 依据 AIModelEntity.supports_prompt_content_type 做特性判定,不支持的类型降级为文本说明。该评论声明已完成单元测试,且当前轮文件不受影响。该 PR 的实际合并状态需通过 GitHub API 查询确认,issue 本身仍为 open,评论中未出现维护者的合并记录或确认回复。因此不能表述为「已修复」或「已随版本发布」。 路径三:在应用层规避类型不匹配。 依据报错报文,服务端只接受清单内的类型。据 issue 讨论的机制判断,问题出在历史重放的 content part 类型上。在应用层可考虑的处理方向是调整历史上下文的构造方式,避免把不受支持的 part 类型送入模型服务端。需要说明的是,事实依据中未给出具体的实现手段,该功能的具体实现尚未公开,此处不做补充。

常见错误排查

以下条目只依据报错报文与 issue 讨论中实际出现的信息,不引入未在事实中出现的命令或工具。
  • 报错为 Unsupported chat content part type: 'file' 且状态码 400。 这是本 issue 的典型表现。定位方式是对照报文给出的支持类型清单,确认 file 不在其中。据 issue 讨论,触发条件是连续两轮均携带附件并开启记忆。
  • 报错类型为 PluginInvokeError,但内层由模型服务端返回。 该错误包装自模型调用环节,[models] Error: API request failed with status code 400 说明问题在服务端侧,不在 Dify 的请求构造阶段。排查时不要只盯着 Dify 的节点参数。
  • 只在第二轮出现失败,第一轮单独正常。 结合记忆重放机制,第一轮的附件被作为历史 part 重放时才暴露类型不兼容。据 issue 讨论,这与当前轮文件无关。
  • 确认部署形态与版本。 本 issue 的环境为 Dify 1.16.1,Self Hosted (Docker)。版本与部署方式属于该报告的环境信息,其他环境是否一致复现,issue 中未给出。
  • 确认所接入的模型。 本 issue 使用的是 Qwen 3.8-27B-FP8。社区修复思路提到依据模型实体的特性声明做判定,说明不同模型实体声明的支持类型集合可能不同,报错清单也会随之变化。

实践建议

把报错报文里的支持清单当作第一手依据。 服务端返回的 Supported types: 列表是判断类型兼容性的直接来源,比猜测模型能力更可靠。出现同类 400 时,先比对 value= 字段的类型名。 区分「当前轮」与「历史轮」两条路径。 据 issue 讨论,当前轮的文件不受本次修复思路的影响,问题集中在历史重放。排查两轮带附件类问题时,可优先在这一层缩小范围。 对记忆重放中的附件保持谨慎。 记忆功能把此前轮次作为 prompt messages 重放,这意味着历史轮次中的任何非文本 part 都会再次进入请求。在多轮附件场景下,历史 part 的类型兼容性需要单独验证,不能默认当前轮可用的类型在历史轮同样可用。 跟踪 PR 的合并状态而非仅看 issue 状态。 issue 为 open 只说明条目未关闭,不代表没有进行中的修复。核实方式是通过 GitHub API 查询 PR #41192 的状态,官方发布说明确认已包含与代码合并进主干属于两种不同说法,不应混为一谈。 低优先级标签不代表问题可忽略。 本 issue 标签包含 review: low,反应合计为 0,但其影响是带附件的多轮对话直接失败,属于功能性阻断。是否需要等待官方方案,取决于业务对多轮附件记忆的依赖程度。

FAQ

问:这个报错是 Dify 的 bug 还是模型服务端的问题? 答:从报文看,400 由模型服务端返回,但触发条件是 Dify 在历史重放中送出了 file 类型的 content part。据 issue 讨论,修复方向落在 Dify 侧对历史 part 的特性判定,而非要求服务端支持 file。 问:当前官方是否已经修复? 答:没有。issue 仍为 open,标签含 review: low。社区成员在评论中说明已提交 PR #41192,但截至末条实质评论,官方未给出复现确认或修复版本号。该 PR 的合并状态需通过 GitHub API 查询确认。 问:临时怎么绕过? 答:据 issue 讨论,可在 Chatflow 应用的 LLM 节点右侧配置面板的 Memory 区域关闭 Memory,或把记忆窗口大小设为 0。代价是失去跨轮次上下文,第一轮附件不再被记忆。 问:只关闭记忆就够了吗? 答:该操作能避开历史 part 重放这一触发路径,但会同时失去第一轮附件的记忆能力,与期望行为不符。它属于规避手段,不是修复。 问:换一个模型能解决吗? 答:issue 中只报告了 Qwen 3.8-27B-FP8 一种模型环境,未提供其他模型的对照结果。社区修复思路提到依据模型实体的特性声明做判定,说明不同模型声明的支持类型集合可能不同,但事实依据中未给出跨模型的验证数据,不做推断。 问:还有哪些信息是缺失的? 答:issue 中未给出完整的请求体、未给出最小复现工程、也未给出维护者的复现结论。错误信息本身提供了类型不匹配的事实,但涉及 Dify 内部如何构造历史 part 的具体实现,该功能的具体实现尚未公开。

订阅 AI 百事知

每周精选 AI 工具评测、行业资讯与使用教程,第一时间送达。

🔗 相关阅读(你可能还想看)

📄 Outlook 节点创建草稿添加附件为何报 UnableToDeserializePostBody?
📄 Flowise 点击市场或聊天页为何整页白屏?
📄 如何解决 Azure AI Search 向量存储的 $filter 递归深度超限错误?
📄 如何解决 shadcn/ui Sidebar 与 Header 重叠的问题?
📄 Next.js 开发服务器为何会 JavaScript heap out of memory?
📄 Nuxt 偶发 Cannot read properties of undefined 报错是怎么回事
📄 如何解决「Visual Studio Code for ipad」相关的问题?
📄 如何在AutoGen中实现企业级代理治理的加密行动收据(AAR)?
📄 记忆内容未清洗直接注入系统提示词,如何防范间接提示注入?
crewAI LiteAgent 将记忆内容直接拼接到系统提示词,存在间接提示注入风险。社区提出分层防御方案,但 iss
🤖 想直接和 AI 对话?
免费体验 DeepSeek V4 等顶级模型,无需注册,随问随答
🎯 立即体验 AI 工具

发表评论

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

🤖 嘟嘟客服
滚动至顶部
🤖 嘟嘟客服
🤖 嘟嘟客服
';i.value='';m.innerHTML+='
...
';fetch('/dify-chat',{method:'POST',headers:{'Content-Type':'application/json'},body:JSON.stringify({query:q,user:'w'+Date.now()})}).then(function(r){return r.json()}).then(function(d){var a=d.answer||'暂时无法回复';m.removeChild(m.lastChild);m.innerHTML+='
'+a+'
'}).catch(function(){m.removeChild(m.lastChild);m.innerHTML+='
网络异常
'})">发送