在 N8N 大学的实战社区里,每天都有成百上千的自动化流程在奔跑。但对很多新手甚至老手来说,Code 节点就像一把双刃剑:用好了它是万能钥匙,用不好它就是报错噩梦。
笔者见过太多同学在深夜对着屏幕抓狂,满屏的红色报错让人头皮发麻。尤其是那个经典的 “Cannot read property ... of undefined”,简直就是 n8n 自动化路上的拦路虎。今天,这篇实战笔记就是来终结这些报错的,带你从“一脸懵逼”走到“运行成功”。
问题复现:那些让人抓狂的红色报错
通常,当你第一次尝试在 n8n 中处理复杂数据结构,或者从 API 响应中提取深层字段时,这个错误就会悄然而至。最典型的场景是:你在 Code 节点里写了一段 JavaScript,试图访问一个对象的属性,比如 items[0].json.user.name。
然后运行一看,控制台抛出一行冷冰冰的代码:
TypeError: Cannot read property 'name' of undefined
或者更笼统的:
Cannot read property 'json' of undefined
这种错误通常发生在数据流经多个节点后,结构发生了变化,或者输入数据本身为空。在 n8n 的 Code 节点中,数据是以 n8n-parsed JSON 对象的形式存在的,直接操作 JS 对象时如果路径不对,就会直接“炸”。
原因分析:为什么代码会“迷路”?
用大白话来说,报错 “Cannot read property of undefined” 的意思就是:**你以为你指着一个房间(对象),但实际上你手指的地方是一片虚空(undefined),然后你还想去拿房间里的桌子(属性),自然就崩了。**
在 n8n 的 Code 节点中,这通常由三个原因造成:
- 数据层级错误: n8n 的数据流是嵌套的。你可能忘记了访问
.json层(这是 n8n 存放实际数据的地方),直接去访问.body或者其他字段。 - 空值(Null/Undefined): 上游节点返回的数据可能为空,或者某个 API 字段缺失。当代码试图访问空值的属性时,就会报错。
- 循环遍历的陷阱: 在使用
for (const item of $input.all())时,如果输入是空的,虽然循环不会执行,但如果你在循环外有逻辑依赖于循环内的变量,也会导致未定义的错误。
解决方案:三招搞定 Code 节点报错
别慌,解决这个问题并不需要你是 JS 大神。N8N 大学为你准备了从易到难的三套方案。
第一招:给属性加个“保镖”(可选链操作符)
这是最常用且最有效的防御性编程技巧。在 JavaScript 中,我们可以使用 可选链操作符(Optional Chaining) ?.。它的作用是:如果前面的对象是 undefined 或 null,表达式会立即停止计算并返回 undefined,而不会报错。
错误写法:
const name = items[0].json.user.name;
正确写法:
const name = items[0]?.json?.user?.name;
这样,即使 user 字段不存在,代码也不会崩溃,而是返回 undefined,你可以通过后续逻辑来处理这个空值。
第二招:设置默认值(空值合并操作符)
为了保证流程继续运行,我们经常需要给获取不到的值一个默认值。这时可以结合使用 空值合并操作符 ??。
实战代码:
const rawData = items[0]?.json;
const userName = rawData?.user?.name ?? "Unknown User";
const userId = rawData?.user?.id ?? 0;
return [{ json: { userName, userId } }];
这段代码的逻辑是:尽力去取值,如果取不到,就用默认值代替。这样你的 n8n 流程就不会因为一个字段缺失而中断。
第三招:数据清洗与断言(进阶)
如果你的上游数据非常脏,比如你确定某个字段一定存在,或者你需要批量处理数据,可以在 Code 节点前加一个 Set 节点或 Function 节点进行预处理。
或者,在 Code 节点中使用更严谨的判断:
// 确保 items 存在且有数据
if (!items || items.length === 0) {
return [];
}
// 遍历处理(更安全)
const newItems = items.map(item => {
const json = item.json;
return {
json: {
// 显式转换,防止类型错误
id: Number(json.user?.id) || 0,
name: String(json.user?.name || '').trim()
}
};
});
return newItems;
这种方法虽然代码量多一点,但能保证你的自动化流程像瑞士钟表一样精准可靠。
避坑指南:Code 节点的常见陷阱
除了上述报错,笔者在 8 年的实战中还总结了两个新手最容易踩的坑:
- 忘记返回值: n8n 的 Code 节点不同于普通的 JS 脚本。你必须显式地
return数据。如果你只做了计算但没有 return,或者 return 的格式不对(不是数组或对象),流程就会挂掉。记住:必须返回包含json键的对象数组。 - 混淆 $input 和 items: 在新版 n8n 中,Code 节点的上下文变量是
items。如果你习惯了旧版的$input或者其他节点的写法,直接使用$input.first()可能会报错。请始终以items作为操作的入口。
FAQ 问答
Q1: 为什么我的 Code 节点在手动执行时报错,但定时触发时又没问题?
A: 这通常是因为手动执行时,输入数据可能为空或结构不同。n8n 的手动执行往往使用默认的测试数据,而实际运行时数据是动态的。建议使用 Webhook 节点配合真实请求进行调试。
Q2: Code 节点里能使用 npm 包吗?
A: 可以,但有限制。在 n8n 云服务中,部分常用包已内置。在自托管(Self-hosted)版本中,你可以通过安装扩展或在 Docker 环境中添加依赖来引入第三方库。不过对于基础的数据处理,原生 JS API 通常足够了。
Q3: 除了 Code 节点,有没有更简单的数据处理方式?
A: 绝对有!除非逻辑非常复杂,否则 N8N 大学强烈建议优先使用 Set 节点(用于重命名或简单映射)和 Spreadsheet File 节点(用于表格处理)。Code 节点是最后的手段,而不是首选。
总结与资源
处理 n8n Code 节点的报错,核心在于理解 JavaScript 的对象访问机制以及 n8n 的数据结构。记住“可选链”和“默认值”这两个法宝,能解决 90% 的 “Cannot read property” 问题。
自动化之路没有一帆风顺,但每一次报错都是进阶的契机。希望这篇实战笔记能帮你扫清障碍。如果你在 n8n 使用中还有其他疑难杂症,欢迎访问 N8N大学 (n8ndx.com),这里有更多硬核的实战指南等着你。