API 突然报错,你的自动化流程是不是直接“死”了?
笔者在 N8N大学 社区里潜水时,经常看到这样的抱怨:“明明昨天还好好的,今天早上起来一看,整个工作流全红了。” 问其原因,多半是某个 HTTP Request 节点调用的第三方 API 突然抽风,或者网络抖动,导致 n8n 直接抛出异常,然后整个流程就断了。

最要命的是,你可能设置了每分钟跑一次,结果 API 报错的那几分钟,你的流程直接“死机”,后续所有数据都积压在那里,或者干脆静默失败,连个响儿都没有。这就是典型的缺乏“代码级容错”意识。今天,笔者就带大家硬核一把,教你在 n8n 的 Code 节点里手写 Try-Catch,把主动权拿回自己手里。
为什么必须掌握 Code 节点的 Try-Catch?
很多刚接触 n8n 的朋友,习惯用“IF”节点来做错误判断。比如:“如果 HTTP Request 返回的状态码不是 200,就走错误分支”。这在小打小闹时还行,但遇到复杂的 API 调用,这种方法就显得很笨拙。
因为 API 的异常不仅仅是状态码的问题,有时候是 DNS 解析失败、连接超时,或者 SSL 证书错误。这些底层错误,IF 节点往往抓不到,n8n 默认的错误处理机制可能直接就“熔断”了整个工作流。
使用 Code 节点(JavaScript)配合 Try-Catch,能让你像写后端代码一样精细控制错误流。这不仅仅是捕获错误,更是为了“优雅地失败”。
实战演练:手写 Try-Catch 捕获 API 异常
准备好了吗?我们直接进入实操环节。假设我们要请求一个不稳定的 API,我们希望即使它报错了,也不要让整个工作流红掉,而是输出一条清晰的自定义日志,继续执行后续流程。
第一步:搭建基础测试环境
为了演示,我们需要一个“定时器”(Cron)触发,接着接一个“HTTP Request”节点。为了让它必报错,我们可以故意请求一个不存在的 URL,或者请求一个会触发 rate limit 的接口。
在 n8n 中,拖入以下节点:
- Trigger: 选择
Schedule/Trigger,设置为每分钟触发一次。 - HTTP Request: 设置 Method 为
GET,URL 填写https://api.example.com/this-will-fail(模拟报错)。
第二步:引入 Code 节点处理异常
这是核心。通常大家会把 HTTP Request 直接连到下一个节点。但我们要在中间插入一个 Code 节点(选择 JavaScript)。
注意:这里的逻辑是把 HTTP Request 的输出作为 Code 节点的输入。但在 n8n 的流式逻辑里,更常见的做法是把 HTTP Request 放在 Try 块里。不过,n8n 的节点是线性执行的,为了在 Code 节点里模拟 Try-Catch,我们需要把 HTTP Request 放在 Code 节点内部执行(高级用法),或者使用 Execute Command 模式。
为了降低门槛,笔者教大家一种**“包裹式”**写法。我们在 Code 节点里,手动发起请求:
// 在 Code 节点的 Code 区域输入以下内容:
try {
// 模拟一个可能会失败的 API 调用
// 在实际场景中,这里可以是 axios.get() 或原生的 fetch()
const response = await $http.request({
method: 'GET',
url: 'https://jsonplaceholder.typicode.com/posts/1', // 这里换成你必报错的 API
});
// 如果成功,把数据传给下一个节点
return { json: { success: true, data: response.data } };
} catch (error) {
// === 核心:这里是捕获异常的地方 ===
// 1. 打印详细错误到 n8n 日志,方便排查
console.error('API 调用失败:', error.message);
// 2. 构建一个自定义的错误输出对象
// 这样后续节点就能识别这是一个“已知的错误”,而不是直接崩溃
return {
json: {
success: false,
error_message: '外部 API 暂时不可用,请稍后重试',
original_error: error.message
}
};
}
第三步:配置 API 调用(关键参数)
在 Code 节点中,使用 $http.request 是最接近原生 n8n HTTP Request 节点的方式。你需要特别注意参数传递:
- Authentication: 如果你的 API 需要 Token,不能直接在 Code 节点里写死。建议在 HTTP Request 节点配置好 Credential,然后在 Code 节点里通过
$credentials调用(如果配置了的话),或者直接把 Token 作为参数传入。 - Headers: 记得带上
Content-Type: application/json。
第四步:验证输出
运行工作流。你会发现,即便 API 报错,Code 节点依然绿色通过,并输出了我们在 Catch 块里定义的那段 JSON:{ "success": false, "error_message": "..." }。
接下来,你可以接一个 IF 节点,判断 {{ $json.success }} 是否为 false,如果是,就走“发送邮件通知我”或者“写入 Google Sheets 记录错误”的分支。这就是容错!
避坑指南:实战中的 3 个致命细节
虽然 Try-Catch 很香,但新手很容易在这里翻车。笔者总结了三个最常见的坑:
-
不要吞掉所有错误: 有些错误是“致命”的(比如数据库连不上、代码语法错误)。如果你把所有
catch (e) {}写成空的,或者只返回一个静默的 success,你会完全不知道流程为什么没产出数据。 一定要记录日志(console.error)或发送警报。 -
Code 节点的数据格式陷阱: n8n 的后续节点非常依赖前一个节点的 JSON 结构。如果你在 Try 里返回的是
{ data: ... },在 Catch 里返回的是{ error: ... },后续节点处理时可能会因为字段不存在而报错。建议统一 JSON 结构,比如都包含一个status字段。 -
异步陷阱: 在 n8n 的 Code 节点(Function Item)中,如果你用了
forEach循环并在里面发请求,一定要用Promise.all或者for...of。否则,n8n 会认为代码执行完了,直接输出结果,而你的异步请求其实还在排队,导致数据丢失。
进阶玩法:结合 n8n 的“继续执行”策略
除了在 Code 节点内部处理,n8n 还有一个全局的“容错”设置,配合 Code 节点使用效果拔群。
在工作流设置中,你可以开启 “On Error” 回调。但更推荐的硬核做法是:
- 将所有可能报错的 HTTP Request 放入一个 Execute Workflow 子流程中。
- 在子流程里,严格执行 Try-Catch。
- 主流程只接收子流程返回的结果,完全不用关心子流程是否报错。
这种架构虽然复杂一点,但维护性极强。当 API 接口变更时,你只需要修改子流程,而不用动主逻辑。
FAQ 常见问题解答
Q1: Code 节点里的 Try-Catch 和 n8n 面板上的“Error Trigger”有什么区别?
A: 区别很大。Error Trigger 是工作流级别的“兜底”,当整个工作流崩溃(比如 Code 节点语法错误、死循环)时才会触发,它通常用来发报警邮件。而 Code 节点里的 Try-Catch 是业务级别的容错,它捕获的是预期的失败(如 API 限流),目的是让流程“软着陆”,继续处理业务逻辑。
Q2: 我不会写 JavaScript,能不能不用 Code 节点做容错?
A: 可以。你可以使用 n8n 自带的 IF 节点,判断 HTTP Request 输出的 $json.statusCode 是否大于等于 400。但这种方法无法捕获网络层面的连接错误(此时 HTTP Request 节点直接红了,不会输出数据给 IF 节点)。所以,Code 节点是目前最稳健的方案。
Q3: 在 Try-Catch 里怎么获取原始的错误堆栈?
A: 在 catch (error) 块中,error 对象通常包含 message(错误信息)和 stack(堆栈信息)。你可以用 error.stack 把详细堆栈打印到 n8n 的控制台(Console),方便你在 Debug 模式下排查具体是哪行代码出了问题。
总结与资源
在 N8N大学,我们一直强调:自动化不仅仅是把手动操作变成自动,更核心的是处理“异常”。一个没有容错机制的自动化流程,就像一辆没有刹车的汽车,跑得越快,翻车越惨。
掌握 Code 节点的 Try-Catch,是你从 n8n 小白进阶为架构师的必经之路。它能让你的自动化系统具备 99.9% 的稳定性。
相关资源推荐:
- n8n 官方文档:Function 节点高级用法
- N8N大学 社区:搜索“错误处理”查看更多实战案例