bbizinets.life
n8nで複数ファイル取得ができない原因|Merge・gzip・Codeノードで詰まった全記録
実践ログ

n8nで複数ファイル取得ができない原因|Merge・gzip・Codeノードで詰まった全記録

# n8nで複数ファイル取得ができない原因|Merge・gzip・Codeノードで詰まった全記録

n8nでGoogle Driveから複数ファイルを並列取得してCodeノードで統合しようとしたとき、以下の症状が連続して発生しました。

  • binaryが読めない(文字化けする・~)^□のような記号になる)
  • Mergeで1 itemになる(4ファイルあるはずなのにOUTPUTが1件だけ)
  • allItemsが取れない($input.all()でアイテム数が常に1になる)

これらは全て別の原因です。結論からお伝えします。この問題は1つの原因ではありません。gzip・Merge・Codeノードの実行モードという3つの独立した問題が重なっています。 それぞれを順番に切り分けることで解決できます。

この記事では、私が実際に経験した3つの詰まりポイントと、Extract from File → Merge(Append)→ Codeという解決フローを整理しています。

結論|複数ファイル処理は「3つの問題」が重なっている

n8nでGoogle Driveの複数ファイルを取得・統合しようとすると、以下の3つの問題が独立して発生します。

問題①:binaryが読めない(gzip問題)

Google DriveのDownload fileノードはgzip圧縮されたbinaryを返します。そのままCodeノードでテキストとして読もうとしても文字化けします。

問題②:Mergeでデータが壊れる(Merge問題)

MergeノードをCombine / Positionで設定すると、4ファイルが1アイテムに圧縮されて最後の1件しか残りません。

問題③:Codeノードが複数回実行される(実行モード問題)

Codeノードのデフォルト設定「Run Once for Each Item」のまま複数入力が来ると、ファイルごとに1回ずつ実行されてデータがバラバラになります。

なぜこの3つは独立しているのか

この3つの問題はそれぞれ発生する場所が違います。gzip問題はDownload fileノードの出力、Merge問題はMergeノードの設定、実行モード問題はCodeノードの設定です。どれか1つを直しても、他の2つは残ったままです。

なぜ順番に潰さないといけないのか

gzip問題を解決してはじめてMergeの出力が正しいかを確認できます。Mergeが正しくなってはじめてCodeノードのアイテム数が正しいかを確認できます。上流の問題が残っていると下流の確認ができないため、この順番で解決する必要があります。

この3つは原因が別々なので、1つ解決しても次の問題が出てきます。順番に切り分けることが重要です。

今回やろうとした構成(Google Drive → 統合)

私が構築したのは記事自動生成パイプラインの一部で、Google Driveから4つのファイルを並列取得してCodeノードで統合し、LLMに渡す構成でした。

[並列4ブランチ]
├ Get create-article.txt(記事生成プロンプト)
├ Get internal_links.csv(内部リンク候補)
├ Get title_and_intro_rules.md(タイトル・導入ルール)
└ Get _index.json(投稿済み記事インデックス)
        ↓
Merge(4ファイルを統合)
        ↓
Code(データを整形してLLMに渡す)

目的はシンプルで、4つのファイルの中身をCodeノードで1つのオブジェクトにまとめてから次のLLMノードに渡すことでした。しかし実際には3つの問題が順番に発生しました。正直、解決まで2時間以上かかりました。

  • 数値:4ファイル・3つの独立した問題・解決まで2時間以上
  • 構造分析:gzip→Merge→実行モードの順に問題が積み重なっていた
  • 判断基準:データが取れない場合 → まず1つのブランチを単体でテストして問題を切り分ける

初心者がつまずくポイント

この問題で詰まる原因の多くは、n8nのデータ形式に関する3つの基本的な概念の違いを知らないことです。

binaryとjsonの違い

n8nのノードが出力するデータには「json」と「binary」の2種類があります。

  • json:テキストや数値など、そのまま読めるデータ。$json.keywordのように参照できる
  • binary:画像・音声・圧縮ファイルなど、そのままでは読めないデータ。Google DriveのDownload fileノードはここにファイルの中身を入れて返す

つまり、Download fileノードの出力をそのままCodeノードで読もうとしても、binaryは$json.dataでは取れません。Extract from Fileノードが「binaryをjsonのtextとして展開する」変換を担います。

Mergeの縦結合と横結合の違い

Mergeノードには大きく2つの動作があります。

  • 横結合(Combine / Position):複数のアイテムを1つにまとめる。フィールド名が同じ場合は上書きされる。4ファイルを横結合すると全てdataフィールドを持つため最後の1件だけが残る
  • 縦結合(Append):アイテムを順番に並べる。4ファイルを縦結合すると4アイテムが並んで出力される

今回のように「各ファイルの中身を個別に保持したまま統合したい」場合は縦結合(Append)が正解です。

Run Onceの意味

Codeノードには2つの実行モードがあります。

  • Run Once for Each Item(デフォルト):受け取ったアイテム1件ずつに対してCodeを実行する。4アイテムが来れば4回実行される
  • Run Once for All Items:受け取った全アイテムをまとめて1回だけ実行する。$input.all()で全アイテムを配列として取得できる

複数アイテムをまとめて処理したい場合は「Run Once for All Items」が必要です。

詰まり①|binaryが読めない(gzip問題)

「Download fileノードでファイルを取得したが、Codeノードで中身を読もうとすると文字化けする」——これが最初の詰まりです。

症状

CodeノードでbinaryデータをBase64デコードしてテキストに変換しようとすると、以下のような文字化けが発生しました。

~)^□+-zo□...(文字化け)

原因

Google DriveのDownload fileノードは、ファイルをgzip圧縮した状態でbinaryとして返します。そのままBuffer.from(data, 'base64').toString('utf-8')で変換しようとしても、gzip圧縮されたバイナリをテキストとして解釈しようとするため文字化けします。

試みた解決策と結果

最初にCompressionノード(Decompress)を使って解凍を試みました。しかし、Compressionノードは単体では動作しますが、Mergeノードを通った後のデータには正しく機能しませんでした。

正しい解決策:Extract from Fileノードを使う

Download fileノードの直後に「Extract from File」ノードを追加します。

設定:

  • Operation:Extract From Text File
  • Input Binary Field:data
  • Destination Output Field:data

これにより、gzip圧縮されたbinaryを自動的に解凍してテキストとしてjson.dataフィールドに格納してくれます。Compressionノードは不要です。

Download file(Google Drive)
→ Extract from File(Operation: Extract From Text File)
→ json.data にテキストが入る

詰まり②|Mergeでデータが壊れる(Merge問題)

「4ブランチからのデータをMergeノードで統合したが、OUTPUTが1アイテムしかなく最後のファイルだけになっている」——これが2番目の詰まりです。

症状

MergeノードのOUTPUTを確認すると、4ファイル分のデータがあるはずなのに1 itemしか表示されません。しかもそのデータは最後に接続した1ファイルのものだけでした。

原因

MergeノードをMode: Combine / Combine By: Positionで設定すると、4つのアイテムが「横結合」されて1アイテムに圧縮されます。このとき、同じフィールド名(data)が上書きされて最後の1件しか残りません。

Input 1: { data: "create-article.txtの中身" }
Input 2: { data: "internal_links.csvの中身" }
Input 3: { data: "title_rules.mdの中身" }
Input 4: { data: "_index.jsonの中身" }
↓ Combine / Position
Output: { data: "_index.jsonの中身" }  ← 最後の1件だけ残る

解決策:AppendモードとInclude Any Unpaired Itemsを使う

MergeノードのModeをAppendに変更し、Options → Include Any Unpaired Itemsをオンにします。

これにより、4つのアイテムが縦に並んで出力されます。

Output[0]: { data: "create-article.txtの中身" }
Output[1]: { data: "internal_links.csvの中身" }
Output[2]: { data: "title_rules.mdの中身" }
Output[3]: { data: "_index.jsonの中身" }

詰まり③|Codeノードが4回実行される(実行モード問題)

「Mergeノードを通った後のCodeノードで、4つのアイテムが全部取れない。毎回1アイテムしか来ていない」——これが3番目の詰まりです。

症状

$input.all()で全アイテムを取得しようとしているのに、デバッグするとアイテム数が常に1になっています。実行回数を見ると4回実行されていました。

原因

CodeノードのデフォルトはSettings → Run Once for Each Itemになっています。Mergeから4アイテムが来ると、アイテムごとに1回ずつCodeノードが実行されるため、毎回$input.all()で取得できるのは1アイテムだけになります。

解決策:Run Once for All Itemsに変更する

CodeノードのSettingsタブを開いて、Run Once for All Itemsに変更します。

これにより、4アイテムがまとめてCodeノードに渡され、$input.all()で全4アイテムが取得できるようになります。

const allItems = $input.all();
console.log('アイテム数:', allItems.length); // → 4

解決フロー|Extract → Merge → Code(再現手順)

3つの問題を切り分けて解決すると、以下のフローが完成します。

[並列4ブランチ]
├ Download file → Extract from File
├ Download file → Extract from File
├ Download file → Extract from File
└ Download file → Extract from File
        ↓
Merge(Mode: Append / Include Any Unpaired Items: ON)
        ↓
Code(Settings: Run Once for All Items)

Step1:各ブランチにExtract from Fileを追加する

全4本のDownload fileノードの直後に、それぞれExtract from Fileノードを追加します。設定は全て同じです。

  • Operation:Extract From Text File
  • Input Binary Field:data
  • Destination Output Field:data

Step2:MergeノードをAppendモードに設定する

Mergeノードの設定を変更します。

  • Mode:Append
  • Number of Inputs:4
  • Options → Include Any Unpaired Items:ON

Step3:CodeノードをRun Once for All Itemsに変更する

CodeノードのSettingsタブで「Run Once for All Items」を選択します。

Step4:Codeノードで順番指定してデータを取得する

MergeのAppendモードでは、Mergeノードへの接続順がそのままallItemsの配列順に反映されます。これはn8nがMergeの入力を「Input 1」「Input 2」という番号で管理しており、その番号順にアイテムを並べるためです。

どのブランチがどの順番になっているかは、Mergeノードを開いてINPUT側のドロップダウンで確認できます(「Input 1:Get create-article」のように表示されます)。

const allItems = $input.all();

// 接続順でファイルを取得(Input 1〜4の順番に対応)
const createArticleText = allItems[0]?.json.data ?? null;
const internalLinksText = allItems[1]?.json.data ?? null;
const titleRulesText    = allItems[2]?.json.data ?? null;
const indexText         = allItems[3]?.json.data ?? null;

// _index.jsonはJSONとしてパース
const indexData = indexText ? JSON.parse(indexText) : null;

// 上流ノードからキーワード情報を引き継ぐ
const manifest = $('Code in JavaScript').first().json;

return [{
  json: {
    keyword:              manifest.keyword,
    intent:               manifest.intent,
    slug:                 manifest.slug,
    index_data:           indexData,
    internal_links_data:  internalLinksText,
    create_article_data:  createArticleText,
    title_rules_data:     titleRulesText
  }
}];

接続順を変更するときのリスク: ワークフローを編集してMergeへの接続順を変えると、allItems[0]〜allItems[3]が取得するファイルが入れ替わります。接続順を変えた場合は必ずCodeノードのインデックスも合わせて修正してください。確認方法はMergeノードのINPUTドロップダウンを見ることです。

判断基準:

  • データが取れない → まず単体のブランチをExtract from FileのOUTPUTで確認する
  • Mergeで1アイテムしか出ない → ModeをAppendに変更してInclude Any Unpaired ItemsをONにする
  • Codeが複数回実行される → Run Once for All Itemsに変更する

判断基準|「動かない」は必ず構造の問題

今回の経験で最も重要だと感じたのは、「3つの問題が独立している」という点です。

gzip問題を解決してもMergeで壊れ、Mergeを修正してもCodeが複数回実行される——それぞれ原因が違うので、1箇所直しても次の問題が出てきます。同じ詰まりを繰り返す人の多くは、「1つ直したのになぜまだ動かないのか」で止まります。構造を分解できていないと、どこに問題があるかが見えないのです。

このとき有効なのが「1ブランチ単体でテストする」という切り分け方法です。

切り分けの手順:

  • 4ブランチのうち1本だけをExtract from FileのOUTPUTでテストする
  • 中身が正しく取れることを確認する
  • 次にMergeをテストして全アイテムが縦に並んでいることを確認する
  • 最後にCodeノードでアイテム数が4になっていることを確認する

この順番で1ステップずつ確認すると、どこで問題が起きているかが特定できます。

この記事で整理した「切り分ける思考」は、n8nに限らずどんな自動化ツールでも使えます。
ただし、「何をどの順番で確認するか」を先に設計しておくには、判断軸の整理が必要です。

→ 判断軸の整理はこちら

この後どうなったか・よくある質問

この解決フローを定着させたことで、4ファイルの並列取得→統合→LLM送信というパイプラインが安定して動くようになりました。現在は同じパターンを使って記事自動生成ワークフロー全体を構築しています。

Q. Extract from FileのOperationは他にも種類がありますか?

あります。CSV・Excel・HTMLなど複数の形式に対応しています。今回はtxt・md・json形式のテキストファイルを扱うため「Extract From Text File」を使いました。バイナリとして扱いたい場合や画像ファイルの場合は別のOperationを選択します。

Q. Mergeノードに接続する順番は重要ですか?

重要です。AppendモードではInput 1・Input 2の接続順にアイテムが並びます。CodeノードでallItems[0]のように順番指定で取得するため、接続順を変えると取得するファイルが入れ替わります。MergeノードのINPUTドロップダウンで接続順を必ず確認してください。

まとめ

n8nで複数ファイルを取得・統合するときの解決フローをまとめます。

  • gzip問題 → Download fileの後にExtract from File(Extract From Text File)を挟む
  • Merge問題 → ModeをAppendに変更してInclude Any Unpaired ItemsをONにする
  • 実行モード問題 → CodeノードをRun Once for All Itemsに変更する
  • データ取得 → allItems[0]〜[3]で接続順に指定して取得する

今日から試せる一歩として、まず1本のブランチだけをExtract from FileのOUTPUTで確認してみてください。中身が正しくテキストとして取れているかを確認するだけで、次に何をすべきかが見えてきます。

動かない原因は必ず構造の問題にあります。切り分ける順番を先に決めることが、解決への最短ルートです。
「何をどの順番で確認するか」を設計する判断基準については、こちらで整理しています。

→ 判断軸の整理はこちら

bizinets.biz

記事を読んで「もっと知りたい」と思ったあなたへ

bizinets.biz では、ビジネスの仕組みづくりを体系的に学べるコンテンツを用意しています。まずは一度、覗いてみてください。

bizinets.biz へ行く →

関連記事