报错现象

一条每天凌晨跑批的工作流(拉第三方接口数据 → 清洗 → 写数据库),平时一直好好的,某天早上发现当天数据没进来。打开 Executions 页面,那条执行是红色失败状态;点开看,断在 HTTP Request 节点上,输出面板里的报错形状大致如下(完整报错原文【待补:从失败执行的输出面板贴出】):

NodeApiError: 请求第三方服务失败
(【待补:替换为实际报错原文,含错误码、出错节点名与发生时间】)

比失败本身更麻烦的是第二层现象:失败之后没有任何人收到通知,全靠第二天早上看数据时才发现——失败是静默的。第三层现象:手动重跑又能成功,说明不是逻辑写错,而是瞬时故障,比如对方限流、超时或连接被重置。

环境

n8n:【待补:版本号】,Docker 部署
工作流节点:Schedule Trigger → HTTP Request → Edit Fields → Postgres
触发:每天凌晨定时执行
数据源:某第三方 REST API【待补:接口方与限流策略】

排查过程

第一步,看执行记录。Executions 列表点进失败那条,画布上断掉的节点带红色标记,右侧输出面板的 error 字段里有结构化信息:error.message 是一句话摘要,error.description 通常携带服务端返回的具体内容。把它与最近一次成功执行的输入输出对照,先排除”参数变了”这种低级原因。

第二步,确认失败模式。往前翻几天到几周的执行记录,看这类失败是偶发还是有规律:固定发生在某个时间点,多半是对方在那个时段维护或限流;随机分布,更像网络抖动。第三方接口限流的典型表现是返回 HTTP 429 状态码【待补:你的接口实际返回什么】。

第三步,检查告警链路。结论是根本没有链路:这个工作流既没配 Error Workflow,也没有任何节点接了错误输出分支,失败只躺在执行历史里,不会推送给任何人。问题从”接口偶尔抽风”升级成”失败无人知晓”,要修的是两层。

根因

两件事叠加:

  1. 瞬时性错误(限流、超时、连接重置)没有重试兜底。n8n 节点默认失败即停,一次请求失败等于整条工作流失败,而这类错误等几秒再试大概率就过了。
  2. 失败没有出口。默认行为下 n8n 不重试、不通知,只在执行历史里留一条红色记录,除非你显式把重试和告警配置上。这不是 bug,是默认值没改。

修复

修复分三层,从节点到工作流再到通知。

第一层,给易错节点开重试。选中 HTTP Request 节点 → 节点右上角 Settings → 打开 Retry On Fail。Max Tries 默认 3 次,Wait Between Tries 默认 1000 ms;对限流场景可以放大到等 5 秒再试。这是节点级开关,写库、发邮件这类下游节点顺手都打开。

第二层,配错误分支。节点 Settings 里的 On Error 有三个选项:Stop the Flow(默认,失败即断)、Continue(忽略错误往下走,用空数据继续)、Continue (using error output)(失败时走一条专门的错误输出分支)。主流程的关键节点选第三种,把错误分支接到 HTTP Request 节点推送到飞书/钉钉群机器人,或接到 Email Send 发邮件——分支里能拿到出错的节点名和错误内容。

第三层,配工作流级错误工作流。新建一个独立工作流,第一个节点用 Error Trigger(触发器列表里找 Error Trigger),后面接通知节点;然后回到主工作流的 Settings → Error Workflow,选中这个新建的工作流。之后这台 n8n 上任何工作流失败都会触发它,Error Trigger 的输出里带失败工作流名、出错节点、报错信息等字段,用 Code 节点拼一条可读的告警文案:

// Error Trigger 之后接 Code 节点:组装告警文案
const e = $json;
return [{
  json: {
    text: [
      '【n8n 告警】工作流执行失败',
      `工作流:${e.workflow?.name ?? '未知'}`,
      `出错节点:${e.execution?.lastNodeExecuted ?? '未知'}`,
      `错误信息:${e.execution?.error?.message ?? '详见执行记录'}`,
      `执行记录:${e.execution?.url ?? '无链接'}`,
    ].join('\n'),
  },
}];

字段结构以 Error Trigger 的实际输出为准【待补:贴一次真实输出的 JSON】。把 text 字段接到飞书/钉钉的 Webhook 节点发出去即可,Webhook 节点用法见《n8n Webhook 触发:接收外部事件实战》。

验证

故意制造失败来验证三层都在工作:把 HTTP Request 的 URL 改成一个不存在的域名,手动执行。预期结果依次出现:节点按 Max Tries 重试 3 次后仍失败;错误工作流被触发,群里收到带工作流名、出错节点、报错信息的告警;Executions 里这条执行标红但告警已送达。然后把 URL 改回去重跑,确认主流程恢复绿色【待补:两次验证的截图】。

n8n 错误工作流触发告警的验证结果

验证时留意一个细节:Error Trigger 工作流自己也是工作流,改动了它同样要点保存激活;有团队把它当成”配完一次再也不看”的东西,等真出事才发现上周的节点改名让告警文案里的字段取空了。每季度用上面这套”故意失败”流程演练一次,比出事时翻配置强得多。

如何预防

  • 把”易错节点开重试”变成新工作流上线的固定动作:外部 API、写库、发消息三类节点统一开 Retry On Fail,主流程关键节点接错误分支。
  • 全实例兜底:先建 Error Trigger 告警工作流,再给每个工作流的 Settings 指定 Error Workflow,别指望”出了问题我会第一时间发现”。
  • 执行历史别一刀切关掉:失败执行是排查的第一现场。n8n 官方提供 EXECUTIONS_DATA_PRUNE 与 EXECUTIONS_DATA_MAX_AGE(单位小时)等环境变量控制保留策略,Docker Compose 里这样配:
environment:
  - EXECUTIONS_DATA_PRUNE=true
  - EXECUTIONS_DATA_MAX_AGE=336   # 保留约两周,按需调整
  • 对第三方 API:先读对方的限流文档,客户端主动控制调用频率;能缓存的响应缓存起来,别把对方的限流阈值当成自己的处理能力。数据落地与库表设计见《n8n 连接数据库:Postgres/MySQL 节点用法》。

相关阅读