Dify 工作流在测试页能跑 / 接到 API 就报错 / 该先查输入变量还是鉴权?

文章导读
遇到预览能跑、接口报错,先把失败方向按状态码拆开:401/403 大概率是鉴权或发布状态,400/422 更像请求体与开始节点变量对不上,404 优先怀疑应用未发布或调用地址不一致。所以不必在输入变量和鉴权之间二选一,而是先用状态码分流,再回到运行历史里比对预览那次真实带了什么输入,最后用最小请求体逐个字段加回去。
📋 目录
  1. 在运行历史里看清预览这次带了什么输入
  2. 核对请求体键名与开始节点变量定义
  3. 确认应用已发布且密钥来自同一应用
  4. 用最小请求体跑通一次再逐项加回
  5. 把错误响应体记下来做分类
A A

遇到预览能跑、接口报错,先把失败方向按状态码拆开:401/403 大概率是鉴权或发布状态,400/422 更像请求体与开始节点变量对不上,404 优先怀疑应用未发布或调用地址不一致。所以不必在输入变量和鉴权之间二选一,而是先用状态码分流,再回到运行历史里比对预览那次真实带了什么输入,最后用最小请求体逐个字段加回去。

先看状态码再决定方向:401/403 基本落在密钥与应用发布状态,400/422 更像请求体键名、类型、必填项与开始节点定义不一致,404 要确认应用是否已发布、调用地址是否指向同一个应用。判断依据来自运行历史里的输入快照和响应体原文,不靠反复试。字段差异往往很小,建议先用最小请求体跑通,再一次只加回一个变量。

在运行历史里看清预览这次带了什么输入

在应用编排页的运行历史或日志面板里,每次在预览区点运行都会留下一条记录,点开可以看到本次运行传给开始节点的输入变量名和取值,以及各节点的执行情况。这条记录就是你的对照基准,先把它记下来,再去比对接口请求体,比凭空猜字段快得多。

同时回到编排画布上的开始节点,看变量定义区,逐个确认每个变量的三件事:变量名(英文标识,不是页面上显示的标签)、类型(文本 / 段落 / 文件 / 数字等)、是否必填。建议整理成三列:

  • 变量名 —— 接口请求里必须逐字一致的那个键
  • 类型 —— 决定请求里传字符串、长文本还是文件引用
  • 本次预览实际传的值 —— 用来判断接口侧少了哪个字段

需要注意,文件类变量在预览里是上传后的对象,接口侧通常不能直接传本地路径或同一个字符串,一般要先通过文件上传拿到标识再引用,具体流程需要结合你使用的版本确认。

核对请求体键名与开始节点变量定义

工作流类应用的调用路径通常是 /v1/workflows/run,对话类应用走 /v1/chat-messages,两种的请求体结构不同,具体以应用概览页给出的示例为准。工作流类应用里,业务变量都放在 inputs 对象下,键名必须与开始节点的变量名完全一致,大小写、下划线、连字符都要对上。

常见的错位写法有这么几类,先对着排一遍:

  • 把页面上显示的中文标签当成键名,实际变量名是 query 之类的英文标识
  • 变量名是 query,请求里写成 textinputmessage
  • 必填变量漏传,或者传了空字符串,被当成未提供
  • 段落类型变量传了对象或数组,接口期望的是字符串
  • 文件类型变量传了 URL 或本地路径,而不是文件标识
  • 数字或布尔类型用字符串传,某些校验会直接拒绝
  • 变量名里带空格或中文,URL 编码和 JSON 转义处理不当
  • 多传了开始节点没有定义的键,被参数校验拦下

判断方法很直接:拿运行历史里的变量名列表和请求体的 inputs 键列表做一次集合比对,缺的、多的、拼写不同的各是哪几个。真正对不上的往往只有一两个字段。

Dify 工作流在测试页能跑 / 接到 API 就报错 / 该先查输入变量还是鉴权?

确认应用已发布且密钥来自同一应用

发布状态通常在应用编排页顶部或应用概览页能看到当前是草稿还是已发布。工作流改动后如果不重新发布,接口调用拿到的一般仍是已发布版本的结果,这是“预览正常、接口行为不一致”的常见来源,需要结合你所在环境的实际行为确认。

API 密钥在应用概览页的 API 访问区域生成,密钥是绑定在具体应用上的。请求头一般写成:

Authorization: Bearer <应用API密钥>
Content-Type: application/json

拿到 401 时,按这个顺序看:密钥是不是复制完整、有没有多余空格或换行、有没有写成 Bearer 之外的前缀、用的密钥是否属于另一个应用、密钥是否已被删除或重置。403 则更偏向权限或额度问题,需要去控制台确认。拿到 404 时,先确认应用是否已发布,再确认调用地址里的应用标识和 API 基础地址是否与当前应用一致,尤其是从别的环境复制过来的地址。

密钥不要写进前端代码或公开仓库,接口调用放在服务端发起比较稳妥。

用最小请求体跑通一次再逐项加回

先用只带一个必填变量的最小请求体跑一次,确认链路本身通:

Dify 工作流在测试页能跑 / 接到 API 就报错 / 该先查输入变量还是鉴权?
curl -X POST 'https://<你的API基础地址>/v1/workflows/run' \
  -H 'Authorization: Bearer <应用API密钥>' \
  -H 'Content-Type: application/json' \
  -d '{
    "inputs": {
      "<必填变量名>": "测试内容"
    },
    "response_mode": "blocking",
    "user": "test-user-001"
  }'

这里的地址、密钥、变量名和 user 都是占位项,需要替换成你自己应用的实际值;user 字段一般需要提供,用来标识调用方。如果连最小请求都失败,问题多半在鉴权、发布状态或路径,而不是变量映射。

跑通之后,一次只加回一个变量:把第二个变量加进 inputs,重新发一次,看返回的状态码和响应体有没有变化。哪一步开始报错,失败范围就锁定在那个字段上。类型敏感的变量(段落、文件、数字)建议单独发一轮,避免多个变量同时出问题时互相干扰。

把错误响应体记下来做分类

不要只看状态码,响应体里通常带着更具体的措辞。无论用哪种客户端,都建议把状态码和响应体原文打印出来:

import requests

r = requests.post(url, headers=headers, json=payload, timeout=60)
print(r.status_code)
print(r.text)

用 curl 时可以加 -i 看响应头,或用 -w '\n%{http_code}\n' 单独打印状态码。把每次的请求体、状态码、响应体原文三样一起记下来,攒几条就能看出规律。

常见措辞对应的检查点大致是这样:提到参数无效、变量缺失、必填字段为空,回到开始节点变量名和类型上核对请求体;提到未授权、令牌无效,检查密钥来源、格式和所属应用;提到应用不存在、工作流未发布,检查发布状态和调用地址;提到频率或额度限制,去控制台确认配额;报错指向某个具体节点,则是工作流内部执行问题,此时输入映射和鉴权通常都是通的。

响应体里如果带了请求标识一类的字段,排查时一并保留,方便和运行历史里的记录对上号。这样每类错误都有固定的检查入口,不用再靠反复试错。