快速结论:当 Dify 把 RAGFlow 数据集接入为 External Knowledge API 时,Dify 会发送一个不带请求体的 POST 请求到 /api/v1/dify/retrieval,导致连接被重置(502;在 Dify 日志中表现为 Reached max retries)。优先检查 RAGFlow 服务端日志中是否出现 h11 的 _SWITCH_UPGRADE 报错;如果出现,基本可以确定 RAGFlow 的 build_error_result 把非 HTTP 的 RetCode 值(例如 101)直接写入了 HTTP 状态码。
适用环境:RAGFlow v0.26.1(有证据表明 main 分支同样存在该问题);docker-compose 部署;DOC_ENGINE=elasticsearch;DEVICE=cpu;Dify v1.14.x;Amazon Linux 2023。Issue 未提供 Python、CUDA、PyTorch 或显卡信息。
最快修复方案:暂无确认的一步修复方案。Issue 中尚未记录合并的修复补丁;用户建议的修复方式是把 build_error_result 中设置的 HTTP 状态码限制为合法的 HTTP 范围(非合法时回退为 400),评论者认为该思路可行,但尚未验证。
注意事项:在补丁合入之前,如果只是临时绕过,需要注意 Dify 的连接测试本身就是不带请求体的请求,可能会触发该异常,因此不能算作真正的修复。直接修改 api/utils/api_utils.py 会影响所有调用 build_error_result 的接口;在没有验证的情况下,应先在看板或测试环境中确认这些接口的返回行为。
问题场景
用户将 RAGFlow 的数据集接入 Dify,作为 External Knowledge API 使用。Dify 在连接测试时调用 http://<host>/api/v1/dify/retrieval。Dify 端的 check_endpoint_and_api_key 只携带 Authorization 头,不发送请求体;RAGFlow 端正确判定缺失 knowledge_id / query 参数并调用 build_error_result,但随后连接被重置,经过前置 nginx 或其他中间层时呈现为 502。
报错原文
failed to connect to the endpoint: http://<host>/api/v1/dify/retrieval
core.helper.ssrf_proxy.MaxRetriesExceededError: Reached maximum retries (3) for URL .../api/v1/dify/retrieval
HTTP Request: POST .../api/v1/dify/retrieval "HTTP/1.1 502 Bad Gateway"
h11._util.LocalProtocolError: Received server _SWITCH_UPGRADE event without a pending proposal
h11._util.LocalProtocolError: Can't send data when our state is ERROR
[ERROR] Error in ASGI Framework
原因分析
最可能的原因是 api/utils/api_utils.py 中的 build_error_result 把 RetCode 枚举值直接赋给了 response.status_code。RetCode 同时包含标准 HTTP 码(如 BAD_REQUEST=400、NOT_FOUND=404、SERVER_ERROR=500)和自定义应用级码(EXCEPTION_ERROR=100、ARGUMENT_ERROR=101、DATA_ERROR=102、AUTHENTICATION_ERROR=109)。当传入 ARGUMENT_ERROR 时,响应状态码变成 HTTP 101 Switching Protocols;Hypercorn/h11 因为没有客户端发起的升级请求而判定为协议异常,于是中止连接,上游断开后表现为 502。凡是使用非标准 HTTP 状态码的 RetCode,都可能触发同样的问题。
环境排查
- 确认 RAGFlow 版本(Issue 中确认 v0.26.1,且 main 分支同样存在)
- 确认 Dify 版本(Issue 中为 v1.14.x)及 External Knowledge API 配置的端点与 API Key
- 确认部署方式与中间层:docker-compose、DOC_ENGINE=elasticsearch、DEVICE=cpu,以及是否存在前置 nginx 或其他反向代理
- 查看 RAGFlow 服务端日志中是否出现 _SWITCH_UPGRADE 或 Can’t send data when our state is ERROR
- Issue 未涉及 Python、CUDA、PyTorch、显卡等版本,暂不需要作为排查项
解决步骤
- 先进行复现确认:使用有效 API Key,向 http://<host>:9380/api/v1/dify/retrieval 发送不带请求体的 POST 请求,观察是否出现连接重置或空响应;同时查看服务端是否输出 h11 报错。
- 作为对照,再发送一次带有效 JSON 请求体的 POST 请求;如果返回 HTTP 200,则说明问题只出现在参数错误分支,符合本 Issue 的判断。
- 可优先尝试(尚未在上游验证):检查 api/utils/api_utils.py 中 build_error_result 对 status_code 的赋值。Issue 建议在赋值前做范围校验,仅在 200–599 之间使用该值,否则回退为 400,并保留 JSON 体中原始的 code。
- 评论者提出的替代思路(同样未验证):为 RetCode 建立显式的 HTTP 映射,例如 ARGUMENT_ERROR→400、AUTHENTICATION_ERROR→401、EXCEPTION_ERROR→500,同时在响应体中保留原始 RetCode。
- 关注上游修复进展。Issue 提到 #14169、#13860、#15028、#15652 等 PR 改进了该端点的错误处理一致性,但没有解决把非标准状态码用作 HTTP 状态码这一根本问题,因此升级前需要确认目标版本是否已经包含相应修复。
验证方法
重新执行不带请求体的 POST 请求,预期得到正常的 HTTP 错误响应(如 400),或返回 200 且响应体中包含 {“code”: 101, …},而不再出现连接重置或 502;服务端日志中不再出现 h11 的 _SWITCH_UPGRADE 或 Can’t send data when our state is ERROR。随后在 Dify 中重新执行 External Knowledge API 的连接测试,确认不再报 Reached max retries / 502。
参考来源
AI 工具推荐
想把多个 AI 模型放在一个入口?
GamsGo AI 集成 ChatGPT、DeepSeek、Gemini、Claude、Midjourney、Veo 等常用模型,适合写作、绘图、视频和日常 AI 工作流。
推广链接:通过此链接购买,我可能获得佣金,不影响你的价格。
这个方案解决了吗?
可以继续搜索完整报错,或查看同一工具的其他排查指南。

![[FEATURE] Extend shared native LLM content and usage contracts to Bedrock](https://www.chat-gpts.plus/wp-content/uploads/2026/11/8128-94a65184-768x403.jpg)
![[Bug]: response_cost is null and spend stays $0 when custom_llm_provider=anthropic and the priced row lives under a different provider](https://www.chat-gpts.plus/wp-content/uploads/2026/11/47675-f09593c8-768x403.jpg)