dify流程执行没有报错,但是API没有返回值

补充的信息很关键,谢谢!

先把关键信息整理一下:

  • Dify 版本:1.11.0
  • 流程结构:多路 LLM → 代码执行 3 → 「直接回复」
  • 直接回复节点配置:只简单引用 {{ 代码执行 3.result }}
  • 你确认:代码执行 3result 总是一段正常、可解析的 JSON 字符串(Markdown 形式)
  • 异常时:HTTP 接口这边整个没有返回,像是请求一直挂着 / 超时,没有拿到任何响应体

这几个点叠加在一起,问题就不再是“answer 字段有时为空”,而更像是:

工作流内部全跑完,但在把「直接回复」结果写回 HTTP 响应这一步,偶发性卡死/失败(可能是后端 bug 或特定内容触发了异常),导致客户端拿不到任何 HTTP 返回。

下面我按“疑似原因 + 建议排查/规避办法”来讲,你可以一步步试:


1. 先排除:是不是请求还在跑、只是你等得不够久?

在 1.11.0 里,如果 Workflow 里节点很多、且都串/并行调用 LLM,有时一次执行要好几分钟。
请你确认两点:

  1. 在“没有返回”的那些请求里:

    • 工作流日志是否立刻显示「直接回复」节点已经成功执行?
    • 还是日志这边也要等很久才看到「直接回复」变绿 :white_check_mark:
  2. 在客户端:

    • 你那边是自己设置了超时时间(比如 HTTP client 30 秒超时)吗?
      如果是,你可能在服务器还没返回前就主动断开了请求,这种情况本地看起来也是“完全没返回”。

建议快速试一下:

  • 用 Postman / curl 发同样的 API 请求,并把 HTTP 客户端超时设长一些(例如 300 秒):
    • 如果 Postman 最后能拿到结果,而你代码里拿不到,多半是你代码里的超时设置问题;
    • 如果 Postman 也一直挂着不返回,那才是 Dify 侧真正“没写回响应”。

2. 查看失败那次的「会话日志详情」里,是否有异常堆栈

虽然你说「流程执行没有报错」,但有两种情况需要特别看:

  1. 整条执行日志
    打开「对话日志」右上角的“详情”/“追踪”,看最底部是否有「系统错误」「内部错误」之类的小红标记。

  2. 直接回复节点内部日志

    • 点开「直接回复」节点,看看是否有“渲染失败”“模板错误”的提示;
    • 例如:变量不存在、Jinja 模板错误等,有时 UI 只显示一个黄/红小图标,不一定显眼。

如果你在这些地方看到错误信息,可以贴出来(注意脱敏),我可以帮你翻译成具体原因。


3. 针对“result 是 JSON 字符串”做一个小改造测试

因为你说 result 是“Markdown 形式的一串 JSON 字符串”,要排除两件事:

  1. JSON 前后是否有 Markdown 符号(比如 json 代码块、反引号、前缀文本等),对话日志里看着“能格式化”,但后端在处理/记录时可能有额外逻辑;
  2. 某些特殊字符(控制字符、极长单行、特殊 Unicode)偶发触发了序列化异常。

建议你先做一个最小修改:

代码执行 3 里把返回改成真正的对象,而不是“JSON 字符串”:

import json

# 假设你现在的 result 是一个字符串 json_str
data = json.loads(json_str)   # 先转成 Python 对象

return {
    "safe_result": data
}

然后把「直接回复」节点改成:

{{ nodes["代码执行 3"].outputs.safe_result | tojson }}

或者干脆只输出一个固定文本:

调试:OK

分两步测试:

  1. 只输出固定文本 调试:OK
    • 如果此时 再也没有“没返回”的情况,说明问题高度集中在“那段 JSON 字符串内容本身”;
  2. 再改为 | tojson 的方式输出对象:
    • 如果也稳定,说明以前那种“直接用 Markdown JSON 字符串”的方式,可能在极端情况下会触发某种序列化/编码异常。

4. 看看是不是「异步触发 / Webhook」类的问题

你前面说“无返回的 http 响应,是直接没有返回,没有调用返回的接口”。
我想确认一下你用的到底是:

  • 标准同步接口(例如 /v1/workflows/trigger/v1/chat-messages,期望立即返回 answer);
  • 还是用了「异步模式」(例如配了 Webhook、轮询结果等),这时正常行为就是初次调用不直接带结果。

如果你不确定,可以把你调用的 URL 形如:

POST /v1/workflows/trigger

或者:

POST /v1/workflows/events

这样的路径贴出来(不含域名、token),我帮你判断。


5. 结合 1.11.0 的状态:建议多加一层“保护”+“日志”

目前看到的现象比较像是:

  • 大部分时间一切正常;
  • 偶发“某种输入 + 某种 JSON 内容”导致内部把响应写回时抛异常(或超时),UI 只看到节点执行成功,但 HTTP 通道挂起。

在你没法立刻升级 / 排查源码之前,可以先用“防御性写法”尽量避免触发边缘情况:

  1. 代码执行 3 里,把最终要返回的 result 做一次兜底处理:

    import json
    from datetime import datetime
    
    def safe_result(raw):
        try:
            # 如果本来就是 dict,直接返回
            if isinstance(raw, dict):
                return raw
            # 如果是字符串,尝试解析
            if isinstance(raw, str):
                return json.loads(raw)
        except Exception as e:
            return {
                "error": "json_parse_failed",
                "message": str(e),
                "raw": raw,
                "time": datetime.utcnow().isoformat()
            }
        # 其它类型直接包装
        return {
            "wrapped": raw,
            "time": datetime.utcnow().isoformat()
        }
    
    # 你原来生成的 json 字符串叫 raw_json
    return {
        "result": safe_result(raw_json)
    }
    
  2. 「直接回复」节点里统一用:

    {{ nodes["代码执行 3"].outputs.result | tojson }}
    

这样做的好处是:

  • 就算遇到奇怪内容,最多是你拿到一个包含 error: json_parse_failed 的 JSON,而不至于整条 HTTP 请求无返回。

6. 如果方便的话,再补两样信息

为了进一步判断是“内容问题”还是“后端 bug”,你可以后续再补充:

  1. 一次“正常返回”的完整 HTTP 响应(脱敏后),以及那次对应的「直接回复」节点 answer 文本;
  2. 一次“没有返回”的对应「对话日志截图」(从开始到直接回复节点,确认所有节点都是绿勾),尤其是直接回复节点内部显示的内容。

我可以根据这两组对比,判断:

  • 是否是**特定大小(特别长的 JSON)**导致的问题;
  • 是否包含特殊字符 / Emoji / 控制字符;
  • 是否有明显的模式(例如只有在某几个 LLM 分支生成特定内容时才会挂)。

总结一下目前的建议操作顺序

  1. 用 Postman/curl 直接调接口,拉长超时时间,确认是 Dify 真没回还是客户端超时。
  2. 改造「直接回复」节点先输出固定文本,看还会不会出现“空 HTTP 返回”。
  3. 把 JSON 改为“对象 + tojson 输出”的方式,避免直接传 Markdown JSON 字符串。
  4. 在代码节点里加安全包装和错误信息,防止因极端 JSON 内容导致内部异常。
  5. 如果经过 2、3 步后问题消失,可以考虑这是 1.11.0 某种内容相关的 bug,建议后续有条件的话升级到更高版本,或者把这条 issue 反馈到 GitHub 附上可复现样例。

如果你愿意,可以先试第 2 步:把「直接回复」改成固定文本,看接下来几十次调用里是否还出现“完全没返回”的情况;有结果后再一起往下分析。