n8n 中二进制数据丢失的修复指南:用 Merge 节点与 n8n-mcp 在 JSON 变换后重新挂载 $binary

发布时间:2026/9/13 9:19:10
n8n 中二进制数据丢失的修复指南:用 Merge 节点与 n8n-mcp 在 JSON 变换后重新挂载 $binary n8n 中二进制数据丢失的修复指南用 Merge 节点与 n8n-mcp 在 JSON 变换后重新挂载 $binary【免费下载链接】n8n-mcpA MCP for Claude Desktop / Claude Code / Windsurf / Cursor to build n8n workflows for you项目地址: https://gitcode.com/GitHub_Trending/n8/n8n-mcp导读在 n8n 工作流中一个最隐蔽的故障模式是数据项同时携带json与binary两个槽位经过只处理 JSON 的节点Edit Fields、Code、IF后binary槽位被静默丢弃而下游三、五步之后的邮件节点再也找不到附件可挂——全程无报错、无校验警告只有一个文件神秘消失的结果。本篇指南以 n8n-mcp 仓库中的 MERGE_FOR_CONTEXT.md 为核心讲解分流 按位置合并Merge: combineByPosition的修复模式并给出通过n8n_update_partial_workflow与get_node在 AI 助手场景下实际接线、配置与验证的完整方案。读完你将掌握识别 binary 剥离点、设计 bypass 分支、正确配置 Merge 节点、以及用执行记录而非校验来确认文件真的存活。问题$json与$binary是两个独立槽位n8n 的每个数据项item都有两个互不相干的顶层键json存放结构化数据binary存放文件字节。这一点在技能总览 README.md 与 BINARY_BASICS.md 中反复强调重写json的变换不会自动携带binary反之亦然。{ json: { customerId: 42, status: sent }, binary: { invoice: { data: base64-encoded bytes, mimeType: application/pdf, fileName: invoice-42.pdf, fileExtension: pdf, fileSize: 12 kB } } }binary内部的键名上例中的invoice称为binary property namedata是多数节点使用的默认名文件处理节点通过binaryPropertyName参数指向这个键生产方命名槽位消费方按名引用名字对不上就是文件没挂上最常见的根因之一。问题由此而来只处理 JSON 的节点在重建输出时不会保留binary槽位。一个典型的场景链是[下载 PDF 的 HTTP Request] → [Edit Fields 改字段] → [IF 判断] → [Send Email 挂附件]PDF 字节在 HTTP Request 输出时位于$binary.dataEdit Fields 重写了$jsonbinary 槽被丢弃IF 继续路由无 binary 的项最后邮件节点拿着binaryPropertyName去找一个已经不存在的槽位——附件为空。没有错误没有警告只有缺失的文件。这正是 MERGE_FOR_CONTEXT.md 开头所描述的common, maddening bug。核心模式在源头分流让 binary 走一条不碰它的旁路修复思路不是去修复变换节点而是在源头把数据流拆成两支最后再合回来[Source with binary] ─┬─→ [Edit Fields: change JSON] ─┐ │ (binary stripped here) │ │ ├─→ [Merge: combineByPosition] ─→ [Email: attach] │ │ └──────────────────────────────────┘ (bypass — binary passes through unchanged)变换支transform branch承担全部 JSON 工作改字段、跑逻辑、做判断binary 在这支上丢失也无妨——这支只负责贡献 JSON。旁路支bypass branch承载原始数据项binary 完好无损不需要任何节点直接把连接线从源头拉到 Merge 即可。合并结果JSON 来自变换支binary 来自旁路支二者重新拼回同一个 item。这里的 Merge 节点与 n8n-node-configuration 技能data/skills/n8n-node-configuration/README.md中讲解的是同一个节点只是在本场景中专门用于重新挂载 binary。这也是技能总览中Binary is silently stripped by JSON-only transforms — pass it through or Merge it back这条核心规则的落地操作。用 n8n-mcp 接线n8n_update_partial_workflow在 Claude Desktop / Claude Code / Windsurf / Cursor 等 AI 编码环境中n8n-mcp 暴露了n8n_update_partial_workflow工具用于增量 diff 式改工作流。当前工作流里源节点已经接好了变换支你只需补充旁路连接和 Merge 节点{ operations: [ { type: addNode, node: { name: Merge, type: n8n-nodes-base.merge, parameters: { mode: combine, combineBy: combineByPosition } }}, { type: addConnection, source: Edit Fields, target: Merge, targetInput: 0 }, { type: addConnection, source: Source, target: Merge, targetInput: 1 }, { type: addConnection, source: Merge, target: Send Email } ] }该工具的完整契约20 种 diff 操作、原子模式、自动清理、自动消毒等记录在 n8n-update-partial-workflow.ts 中。与本文直接相关的要点addNode要求提供节点的name、type、position示例中为简洁省略了position实际调用时应补上坐标如position: [800, 300]。addConnection按source → target建连targetInput指定目标节点的输入口索引。依赖关系上注意操作顺序必须先addNode再加连接因为连接的校验依赖节点已存在工具文档 pitfall 中明确must add node before connecting to it。建议在每次调用带上intent参数如Re-attach binary after Edit Fields strips it这是该工具的明确最佳实践。版本差异先get_node确认参数形状Merge 节点的参数名在不同版本间发生过漂移mode、combineBy、combineByPosition的拼写以及numberOfInputs的表达方式在不同 n8n 版本中可能不同。原文档给出的原则是原理稳定字段名会动The principle is stable; the field names move。因此在提交结构前务必用 n8n-mcp 的get_node工具针对用户实际使用的 n8n 版本确认当前形状get_node({nodeType: nodes-base.merge, detail: standard})get_node支持minimal / standard / full三种详情粒度与docs / search_properties / versions / compare等模式完整用法见 get-node.ts。detailstandard覆盖大多数需求若要确认numberOfInputs这类字段的准确拼写与默认值可用modesearch_properties配合propertyQuery或用modeversions对比版本间变化。两个必踩的接线细节Merge 默认只有 2 个输入口。若你接 3 条以上分支必须把输入口数量调到与实际分支数一致否则多余的分支会被静默丢弃。连接输入索引从 0 开始。上面的旁路支落在targetInput: 1第二个输入口变换支在targetInput: 0。接错索引会导致配错对或分支整体丢失。配置 Merge位置合并是默认正确选择用于重新挂载 binary 时应当使用按位置合并position-based combination。四种模式对比如下模式行为可用于 binary 重挂combineByPosition把输入 1 的第 N 项与输入 2 的第 N 项配对✅ 是combineBySql/combineByFields按键做 join仅当两支共享连接键combineAll笛卡尔积N×M 项❌ 否——项数爆炸append输入首尾相接拼接❌ 否——不做配对选择combineByPosition的理由很直接它把 item 数保持在 N且把每个变换后的 JSON 项与对应的、携带 binary 的原始项配对。要保证配对正确两支输出的项顺序与数量必须一致——当两支共享同一个源时天然满足。仓库中其他技能对 Merge 模式的告诫也佐证了这一选择比如 ai_agent_workflow.md 指出并行 Agent 汇聚时combineAll做笛卡尔积并可能因输入到达时间不同产生 0 输出这正是模式选错导致结果爆炸/为空的同类教训。为什么它能生效Merge 节点合并它配对的两个 item 的全部内容——既包括json也包括binary。当一个输入持有你想要的 JSON、另一个输入持有你想要的 binary 时合并后的 item 就同时携带两者。binary 之所以存活是因为它走的那条分支从未被任何节点触碰过。这也解释了为什么旁路支不需要任何节点任何额外的变换节点都可能是新的剥离点最稳妥的旁路就是一条从源头直连 Merge 的裸连接。更便宜的替代在变换节点上直接透传如果变换节点自己就能保留 binary那么应该优先用它——一个节点能解决的事不必上三个节点的分流合并Edit Fields (Set)启用includeOtherFields让节点把未提及的字段以及 binary 槽位一起带过去。Code 节点在返回的 item 中显式带上binary: $input.item.binary详细读写配方见 BINARY_BASICS.md// Code node, Run Once for Each Item const buffer await this.helpers.getBinaryDataBuffer(0, data); // (itemIndex, propertyName) const text buffer.toString(utf-8); return [{ json: { ...$json, length: buffer.length }, binary: $input.item.binary, // ← 不返回 binary文件就在这个节点上消失 }];注意getBinaryDataBuffer会正确处理 n8n 的内存/文件系统两种存储模式不要自己去 base64 解码$binary.key.data。IF / Filter这类节点是路由而非重建通常会在透传的 item 上保留 binary——但不要假设要在执行记录里验证。只有两种情况下才回到 Merge变换节点确实无法携带 binary或 JSON 与 binary 来自完全不同的上游节点。什么时候 Merge 也不够用如果链路中有多个剥离点在每个节点处都做分流 合并会变成一场维护噩梦——工作量与脆弱性都失控。两条更优路线尽早上传Upload early字节一产生就推到对象存储把 URL/键作为普通 JSON 字段传遍整条链JSON 在任何变换下都安然无恙只在真正需要字节的节点处重新拉取。这也是大文件的正确做法——二进制槽位进入 n8n 执行数据库几十 MB 起步就会拖慢实例100 MB 以上必须外置存储详见 BINARY_BASICS.md 的尺寸指导表。把 binary 处理推进子工作流把文件交给一个专门做二进制处理的子工作流让它返回最终结果。关键陷阱在于Execute Workflow Trigger 的输入模式默认的 typed-input 模式只携带具名 JSON 字段、会丢弃$binary若子工作流必须直接接收字节要改用 passthrough 输入模式。一旦剥离点超过两三个尽早上传或子工作流通常比让长链上每个节点都对 binary 保持忠诚更省事、更不易碎。合并后如何验证执行记录而非校验被合并却仍然丢失的 binary不会在校验中暴露——validate_workflow看不到 binary 槽是否存活这是一个静默失败。唯一可靠的检查手段是执行记录用n8n_test_workflow运行工作流再用n8n_executions拉取本次执行。看 Merge 节点的输出确认合并后的 item 同时具备变换支的json和旁路支的binary。若 binary 缺失检查 Merge 模式有些模式并不按你预期的方式配对并确认旁路支在进入 Merge 前确实带着 binary。在 BINARY_BASICS.md 中有同样的判断标准执行记录中binary槽位最后出现在哪个节点、又在下一个节点消失那里就是需要插入透传或 Merge 的位置。即使 base64 内容过大无法完整渲染槽位的存在性、元数据名称、mime 类型、大小也足以判断。常见错误速查表错误症状修复发现剥离太晚原始 binary 已经没了开发时在每个节点后检查执行记录合并单源链但没有旁路没有可合并的对象binary 仍缺失在源头分流让 binary 走旁路支该用combineByPosition却用了combineAllN×M 项而非 N 项刻意选择模式旁路支接错输入索引配对错误或分支被丢弃连接索引 0 基用n8n_get_workflow核对忘记把 Merge 输入口调到 2 以上第三条分支静默丢弃输入口数量与实际接线分支一致补充一个与本主题直接相关的 n8n-mcp 工具细节n8n_update_partial_workflow的addConnection对 IF/Switch 这类多输出节点支持语义参数branchtrue/false、caseN但 Merge 是普通多输入节点必须用 0 基的targetInput精确指定输入口——这恰好呼应了上表输入索引一行的常见坑。接线完成后可用n8n_get_workflowmodestructure核对连接结构是否符合预期见 n8n-update-partial-workflow.ts 的返回值说明。小结Binary 丢失的根因在 n8n 的数据模型里是结构性的$json与$binary并行独立JSON 变换天然不携带文件字节。应对顺序应当是优先透传——Edit Fields 开includeOtherFields、Code 节点显式返回binary透传不了就用 Merge 按位置合并——源头分流旁路保 binarycombineByPosition配对剥离点太多就换架构——尽早上传走 URL或把 binary 工作推给子工作流验证永远靠执行记录——n8n_test_workflown8n_executions看 binary 槽位是否跨过 Merge。记住 n8n 二进制技能README.md的那句话两个槽位并排而行。数据乘$json文件乘$binary——而一旦文件穿越 AI 工具边界或抵达聊天界面它将以 URL 而非字节的形式旅行。【免费下载链接】n8n-mcpA MCP for Claude Desktop / Claude Code / Windsurf / Cursor to build n8n workflows for you项目地址: https://gitcode.com/GitHub_Trending/n8/n8n-mcp创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考