n8n-debugging
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
Chinesen8n Debugging
n8n 调试
When something breaks, the cause is almost always:
- Parameter misconfiguration (wrong value, wrong type, missing field).
- Stale assumptions (different version, different behavior than you remember).
- Paths misconfigured or misconnected (wrong output index, wrong merge input, missing wire, IF/Switch wired to the wrong branch).
- Upstream data stripped (an intermediate node replaced with its own output, so downstream
$jsonresolves to null even though "it should be there"). Fix: reference the stable upstream node by name ($json.x).$('Earlier Node').item.json.x - Item context lost (after Aggregate, Execute Once, or Split Out flows, n8n can't pair references deterministically, error reads like "The expression is referencing... multiple matching items"). Fix: Merge node to re-establish context,
.itemfor explicit lookup, or redesign to keep item correspondence stable (e.g., split into stateless sub-workflows).$input.all().find(...) - Logical errors (the wires are right and the parameters are right, but the workflow does the wrong thing, same as a logic bug in code).
- Genuine bug (rare but real).
Diagnose systematically: cheap checks first, deeper investigation only when those fail.
当工作流出现问题时,原因几乎总是以下情况之一:
- 参数配置错误(值错误、类型错误、字段缺失)。
- 过时的假设(版本不同、行为与记忆中不符)。
- 路径配置或连接错误(输出索引错误、合并输入错误、连线缺失、IF/Switch连接到错误分支)。
- 上游数据被覆盖(中间节点用自身输出替换了,导致下游
$json解析为null,尽管“它应该存在”)。修复方法:通过名称引用稳定的上游节点($json.x)。$('Earlier Node').item.json.x - 项目上下文丢失(在Aggregate、Execute Once或Split Out流程之后,n8n无法确定性地匹配引用,错误信息类似“表达式引用了...多个匹配项”)。修复方法:使用Merge节点重新建立上下文,使用
.item进行显式查找,或重新设计以保持项目对应关系稳定(例如,拆分为无状态子工作流)。$input.all().find(...) - 逻辑错误(连线和参数都正确,但工作流执行了错误操作,与代码中的逻辑bug类似)。
- 真实bug(罕见但确实存在)。
系统地进行诊断:先做简单检查,只有当这些检查失败时再进行深入调查。
Non-negotiable
不可协商原则
Believe the user. "This isn't working" means something isn't behaving as they expect, even if they describe the symptom imprecisely. Don't dismiss with "it should work" or "are you sure you're doing X?". Investigate first: the user is truth about what should happen, execution data and source are truth about what is happening. When you can't find the cause, "I don't know yet" beats a plausible-sounding fabrication.
相信用户。“这不管用”意味着某些行为不符合他们的预期,即使他们对症状的描述不够精确。不要用“它应该能工作”或“你确定你在做X吗?”来否定用户的反馈。先进行调查:用户对“应该发生什么”的描述是真实的,执行数据和源代码是对“实际发生了什么”的真实反映。当你找不到原因时,“我还不知道”比听起来合理的编造更好。
Strong defaults (cause to cheap check)
优先检查的常见原因(按可能性排序)
Match cause to cheap check, in order of likelihood:
- Parameter misconfiguration → re-fetch via , compare against
get_node_types, look for type/value/missing-field mismatches.get_workflow_details
- Stale assumptions → ask the n8n version, ask when the user last updated the skills plugin, suspect drift if behavior contradicts the skill.
- Paths misconfigured or misconnected → inspect the object, verify each output index and merge input (see
connections).n8n-connections - Upstream data stripped → trace references back through the chain, look for any node that replaces the json with its own output. Common offenders: Aggregate, HTTP-binary, Extract from File, Code in "Run for All Items" mode, branching Merge. Not exhaustive: any node can do this if its output shape doesn't include the upstream fields.
$json.x - Item context lost → check downstream of any Aggregate / Execute Once / Split Out for references, switch to
.itemor a Merge anchor.$input.all().find(...) - Logical errors → trace data through step by step, compare each node's output vs. expected.
get_execution - Genuine bug → fall through to reading the n8n source, then GitHub issues, then a workaround.
For external API problems, the upstream service's API docs (not n8n's wrapper) are the truth. Fetch API docs and n8n's source code to debug if required.
将原因与简单检查对应,按可能性从高到低排列:
- 参数配置错误 → 通过重新获取,与
get_node_types进行对比,查找类型/值/缺失字段不匹配的情况。get_workflow_details
- 过时的假设 → 询问n8n版本,询问用户上次更新技能插件的时间,如果行为与技能描述不符,怀疑版本漂移。
- 路径配置或连接错误 → 检查对象,验证每个输出索引和合并输入(参见
connections)。n8n-connections - 上游数据被覆盖 → 追踪引用的整个链条,查找任何用自身输出替换json的节点。常见的“罪魁祸首”:Aggregate、HTTP-binary、Extract from File、处于“为所有项目运行”模式的Code节点、分支Merge节点。但不限于这些:任何输出结构不包含上游字段的节点都可能导致这种情况。
$json.x - 项目上下文丢失 → 检查Aggregate / Execute Once / Split Out之后的下游是否有引用,切换为
.item或使用Merge锚点。$input.all().find(...) - 逻辑错误 → 通过逐步追踪数据,比较每个节点的输出与预期结果。
get_execution - 真实bug → 最后查看n8n源代码,然后检查GitHub问题,再寻找解决方案。
对于外部API问题,上游服务的API文档(而非n8n的封装)是权威依据。必要时获取API文档和n8n源代码进行调试。
Step-by-step walkthrough
分步排查指南
When the cheap checks above don't immediately pinpoint the cause, work through these in order.
当上述简单检查无法立即确定原因时,按以下步骤依次进行。
Step 1: confirm the symptom
步骤1:确认症状
Ask:
- What did they expect?
- What actually happened?
- Error message text?
- When did it last work? What changed since?
Vague ("it's broken") becomes tractable when concrete ("email sends to wrong address" or "workflow returns 500 with empty body").
询问:
- 他们期望发生什么?
- 实际发生了什么?
- 错误消息文本是什么?
- 它上次正常工作是什么时候?从那以后发生了什么变化?
模糊的描述(“它坏了”)会在具体化后变得易于处理(“邮件发送到了错误的地址”或“工作流返回500错误且响应体为空”)。
Step 2: check the execution
步骤2:检查执行记录
get_execution({ id: <execution_id> })Look at:
- Which node failed?
- What input did it have?
- What error message? Read carefully. Usually points at the cause.
No execution ID? Ask the user to re-run.
get_execution({ id: <execution_id> })查看:
- 哪个节点失败了?
- 它的输入是什么?
- **错误消息是什么?**仔细阅读,通常会指向原因。
没有执行ID?请用户重新运行工作流。
Step 3: re-fetch the workflow
步骤3:重新获取工作流详情
get_workflow_details({ id: <workflow_id> })Confirm the actual current state. The user might be looking at a different workflow or remembering a stale version.
Compare:
- Nodes vs. the user's mental model.
- Connections vs. intent (per 's
n8n-connections).VERIFICATION.md - Credentials vs. expected (per ).
n8n-credentials-and-security - Upstream-strip risk: any node between a data source and a downstream consumer that replaces the json with its own output? Common offenders are HTTP-binary, Extract from File, Aggregate, Code in "Run for All Items" mode, and branching Merge, but any node can do this if its output shape doesn't include the upstream fields. The consumer should reference the source node by name (
$json.x), not$('Source Node').item.json.x. Otherwise the field silently resolves to null.$json - Item-context risk: any Aggregate / Execute Once / Split Out followed by downstream references? n8n may not be able to pair items deterministically. Look for "The expression is referencing... multiple matching items" in past executions.
.item
get_workflow_details({ id: <workflow_id> })确认当前的实际状态。用户可能正在查看不同的工作流或记忆中的旧版本。
对比:
- 节点与用户的认知模型是否一致。
- 连接与预期是否一致(根据的
n8n-connections)。VERIFICATION.md - 凭据与预期是否一致(根据)。
n8n-credentials-and-security - 上游数据覆盖风险:在数据源和下游消费者之间,是否有任何节点用自身输出替换了json?常见的有HTTP-binary、Extract from File、Aggregate、处于“为所有项目运行”模式的Code节点和分支Merge节点,但任何输出结构不包含上游字段的节点都可能导致这种情况。消费者应该通过名称引用源节点(
$json.x),而不是使用$('Source Node').item.json.x。否则字段会静默解析为null。$json - 项目上下文丢失风险:是否有Aggregate / Execute Once / Split Out节点后跟下游引用?n8n可能无法确定性地匹配项目。查看过往执行记录中是否有“表达式引用了...多个匹配项”的错误。
.item
Step 4: re-fetch the node types
步骤4:重新获取节点类型
get_node_types([{ name: '<failed-node>', resource: '...', operation: '...' }])Compare actual parameter shape vs. configured. Common mismatches:
- Missing required parameter.
- Wrong type (string vs. number, etc.).
- and
objectare distinct in n8n's UI type dropdowns (Set, IF, Switch, Filter, anywhere the UI asks you to pick a type). Pickingarraywon't accept an array value, and vice versa. Inside expressions themselves it's normal JS (arrays are objects), so the distinction only bites at those UI type-pick surfaces. Watch for this when aobjectexpression returns the wrong container shape for a typed slot.={{ ... }} - A dependent parameter set without its parent (e.g., without
credentials, orauthentication !== 'none'withoutquery). Re-fetch withoperation === 'executeQuery'passing the right discriminators.get_node_types
get_node_types([{ name: '<failed-node>', resource: '...', operation: '...' }])对比实际参数结构与配置的参数。常见的不匹配情况:
- 缺少必填参数。
- 类型错误(字符串 vs 数字等)。
- n8n的UI类型下拉菜单中和
object是不同的(Set、IF、Switch、Filter等任何UI要求选择类型的地方)。选择array不会接受数组值,反之亦然。在表达式内部是标准JS(数组也是对象),所以这种区别只会在UI类型选择界面产生影响。当object表达式返回的容器形状与类型插槽不匹配时,要注意这一点。={{ ... }} - 设置了依赖参数但未设置其父参数(例如,时设置
authentication !== 'none',或credentials时设置operation === 'executeQuery')。传递正确的鉴别器,通过query重新获取。get_node_types
Step 5: test with pinned data
步骤5:使用固定数据测试
prepare_test_pin_data({ workflowId: '<id>' })
test_workflow({ workflowId: '<id>' })Controlled input isolates "workflow broken?" from "input weird?". If pinned data works but real input fails, the issue is in real input handling.
If pinned data also produces wrong output, that's likely a logical error: trace each node's output against what you expected. on the test run gives you the actual emitted data per step, which is the source of truth for what each node did.
get_executionprepare_test_pin_data({ workflowId: '<id>' })
test_workflow({ workflowId: '<id>' })受控输入可以区分“工作流损坏?”和“输入异常?”。如果固定数据可以正常工作但真实输入失败,问题出在真实输入的处理上。
如果固定数据也产生错误输出,那很可能是逻辑错误:逐步追踪每个节点的输出与预期结果。测试运行的会提供每个步骤实际输出的数据,这是每个节点执行情况的权威依据。
get_executionStep 6: read the n8n source
步骤6:查看n8n源代码
When everything checks out and behavior still seems wrong:
github.com/n8n-io/n8n- for built-in nodes.
packages/nodes-base/nodes/<NodeName> - for execution logic.
packages/cli/src/... - for workflow runtime.
packages/core/src/...
The behavior of the code is truth.
See .
references/FETCHING_N8N_SOURCE.md当所有检查都通过但行为仍然异常时:
github.com/n8n-io/n8n- 内置节点位于。
packages/nodes-base/nodes/<NodeName> - 执行逻辑位于。
packages/cli/src/... - 工作流运行时位于。
packages/core/src/...
代码的行为是权威依据。
参见。
references/FETCHING_N8N_SOURCE.mdStep 7: suspect drift on either side
步骤7:怀疑双方版本漂移
If steps 1-6 all check out and behavior still doesn't match expectations, version drift is the most likely remaining cause. Two sides drift independently:
<!-- TEMPORARY: when instance metadata tool is added, change asking user to just using the tool -->
- Their n8n instance version. Ask. (UI: , or
Settings → About.) On older instances, parameters and tools the skill assumes may be missing; on very new ones, parameter shapes or tool names may have moved. Suggest updating to the latest n8n release, or if a fix is rumored or the issue is recent, the latest beta.GET /rest/settings - This skill plugin's version. These skills drift relative to n8n over time. If the user installed the plugin a while ago, suggest (or the plugin manager's update command) on the skills repo. See the README's "Drift" section.
git pull
Drift surfaces as: parameter shape mismatches in , MCP tools that don't exist or carry new parameters, tool descriptions that contradict what the skill teaches, behavior diverging from the skill's claims. When you spot any of those, surface drift explicitly to the user: "This may be drift between your n8n version and these skills. Can you tell me your n8n version, and when you last updated the skills?"
get_node_typesIf after updating both sides the issue persists, proceed to Step 8.
如果步骤1-6都检查通过但行为仍然不符合预期,版本漂移是最可能的剩余原因。双方可能独立发生漂移:
<!-- TEMPORARY: 当添加实例元数据工具后,将询问用户改为直接使用工具 -->
- 用户的n8n实例版本。询问用户。(UI路径:,或
Settings → About接口。)在旧版本实例中,技能假设存在的参数和工具可能缺失;在非常新的版本中,参数结构或工具名称可能已更改。建议更新到最新的n8n版本,如果有传闻中的修复或问题是最近出现的,建议更新到最新测试版。GET /rest/settings - 本技能插件的版本。这些技能会随着时间推移与n8n产生版本漂移。如果用户安装插件已有一段时间,建议在技能仓库执行(或插件管理器的更新命令)。参见README的“漂移”部分。
git pull
版本漂移的表现:中的参数结构不匹配、MCP工具不存在或带有新参数、工具描述与技能教程矛盾、行为与技能声明不符。当发现这些情况时,明确向用户指出版本漂移:“这可能是你的n8n版本与这些技能之间存在版本漂移。你能告诉我你的n8n版本,以及你上次更新技能的时间吗?”
get_node_types如果更新双方版本后问题仍然存在,继续执行步骤8。
Step 8: report or workaround
步骤8:报告问题或寻找替代方案
For confirmed bugs:
- Have the user post a question on https://community.n8n.io
- Surface a clear repro to the user.
- Check n8n GitHub issues. May already be filed.
- If blocking, work around (different node/approach) and note in workflow notes.
- If a fix is in progress, mark workarounds with
<!-- TEMPORARY: ... -->
对于已确认的bug:
- 让用户在https://community.n8n.io上发布问题。
- 向用户提供清晰的复现步骤。
- 检查n8n的GitHub问题,可能已有相关提交。
- 如果问题阻塞了工作,寻找替代方案(不同节点/方法)并在工作流注释中注明。
- 如果修复正在进行中,在替代方案中标记
<!-- TEMPORARY: ... -->
Reference files
参考文件
| File | Read when |
|---|---|
| Parameters might be misconfigured, need a systematic re-check |
| n8n behavior contradicts docs, need to read the actual code |
| 文件 | 阅读场景 |
|---|---|
| 参数可能配置错误,需要系统地重新检查 |
| n8n行为与文档矛盾,需要查看实际代码 |
Anti-patterns
反模式
| Anti-pattern | What goes wrong | Fix |
|---|---|---|
| "It should work, are you sure you're doing X?" | Dismisses the user's report, misses real issues | Believe the user. Investigate. |
| Re-running without checking the execution | Same failure twice, no new info | |
| Assuming docs are accurate when behavior contradicts | Accepting the wrong mental model | Read the source. Behavior is truth |
| Re-implementing logic in a Code node when a configured node fails | Hides the bug, doesn't fix root cause | Diagnose first, only work around when the bug is confirmed |
| Bisecting by deleting nodes randomly | Wastes time | Step through |
| Asking the user to re-screenshot instead of inspecting via MCP | Slow, error-prone | Use |
| Calling it "fixed" when you've worked around the bug, not understood it | Bug recurs in slightly different form | Document the cause. If working around, mark with |
| Declaring a "bug" without asking the user's n8n version or when they last updated the skills | Real cause is often drift, and user updates and the "bug" disappears | Ask both versions before reporting. See Step 7. |
| 反模式 | 问题所在 | 修复方法 |
|---|---|---|
| “它应该能工作,你确定你在做X吗?” | 否定用户的反馈,错过真实问题 | 相信用户,进行调查 |
| 不检查执行记录就重新运行 | 重复相同的失败,无法获得新信息 | 对失败的运行执行 |
| 当行为与文档矛盾时仍假设文档准确 | 接受错误的认知模型 | 查看源代码,行为是权威依据 |
| 当配置节点失败时在Code节点中重新实现逻辑 | 隐藏bug,不修复根本原因 | 先诊断问题,只有当bug被确认时才寻找替代方案 |
| 通过随机删除节点进行二分排查 | 浪费时间 | 通过 |
| 让用户重新截图而不是通过MCP检查 | 缓慢且容易出错 | 使用 |
| 当你只是找到替代方案而非理解原因时就宣称“已修复” | bug会在稍有不同的场景中再次出现 | 记录原因。如果使用替代方案,标记 |
| 未询问用户的n8n版本或上次更新技能的时间就宣称是“bug” | 真实原因通常是版本漂移,用户更新后“bug”会消失 | 在报告问题前询问两个版本。参见步骤7。 |