n8n ワークフローデバッグ は何をしますか?
n8n ワークフローを、シニアエンジニアのように体系的に修正します。推測ではなく、系統立てて行います。
トリアージ:最初に障害クラスを特定する
ユーザーに質問するか(エラーテキストから推測して)、以下のいずれのクラスに該当するか判断します。
| クラス | 症状 | よくある根本原因 |
|---|---|---|
| 式エラー | Cannot read property X of undefined、赤いノードバッジ | 誤った式構文、= プレフィックス不足、未定義フィールドへのアクセス |
| 型の不一致 | Expected string, got array、下流での奇妙な動作 | Item Lists と単一アイテムの混同、Split In Batches の出力形状 |
| サイレント空出力 | ワークフローはグリーンだが出力や副作用がない | フィルター条件の誤り、古いピンデータ、認証情報のスコープ不足 |
| 認証失敗 | 401、403、Invalid API key | 誤った認証情報の選択、トークンの期限切れ、OAuth リフレッシュ未設定 |
| レート制限 | 断続的な 429、手動では成功、バッチ実行で失敗 | バックオフ未実装、バッチサイズ过大、複数ワークフローでの認証情報共有 |
| サブワークフロー | Execute Workflow が何も返さない、またはエラー | パラメータ未渡し、戻り値未設定、誤ったワークフロー ID |
式エラー
最大の落とし穴:={{ $json.field }} と {{ $json.field }} の違い。先頭の = がフィールドを式として扱います。これがないと、リテラル文字列 {{ $json.field }} が送信されます。
確認手順:
- フィールドをクリック — 「式」トグル(fx アイコン)がハイライト表示されていますか? 表示されていない場合はリテラルモードです。
- コードビューの JSON で、値が
=で始まっていることを確認:"value": "={{ $json.id }}"
未定義パスのアクセス:$json.customer.email は customer が null の場合にエラーをスローします。オプショナルチェーンを使用:$json.customer?.email ?? 'unknown'
先行ノードの参照:$('Node Name').item.json.field を使用し、$node['Node Name'].json.field(非推奨)は使用しないでください。ノード名(スペースを含む)を正確に引用符で囲みます。
よくある式パターン:
// 配列アクセス
{{ $json.items[0].name }}
{{ $json.items?.[0]?.name ?? 'empty' }}
// 先行ノードの出力
{{ $('Webhook').item.json.body.email }}
// 先行ノードの全アイテム(ループ用)
{{ $('Split In Batches').all().map(i => i.json.id) }}
// 条件分岐
{{ $json.amount > 100 ? 'high' : 'low' }}
// 日付フォーマット(n8n は Luxon を使用)
{{ $now.toISO() }}
{{ $now.minus({ days: 7 }).toFormat('yyyy-MM-dd') }}
// 環境変数(セルフホスト)
{{ $env.MY_SECRET }}
型の不一致診断
n8n はデータを アイテムの配列 として渡し、各アイテムは { json: {...}, binary: {...} } という構造を持ちます。多くのバグは、単一アイテムを配列として扱ったり、その逆を行うことで発生します。
調査手順:
- エラーが発生しているノードの入力ビュー(左パネル)を開く
- 確認:それは 1つのアイテム でその中に配列が入っている(
{ json: { list: [...] } })のか、それとも 複数のアイテム([ { json: {} }, { json: {} } ])なのか? - これらは異なる処理が必要です:
- 1アイテムの中に配列がある場合 →
Item Lists→ 「Split Out Items」で展開 - すでに複数アイテムの場合 → アイテムごとに処理
- 1アイテムの中に配列がある場合 →
Split In Batches はメイン出力と「完了」出力で異なる形状を出力します。メイン出力はバッチで、完了出力は空です。適切に配線してください。
サイレント空出力 — 最悪のケース
ワークフローは緑のチェックマークが表示されているが、下流で何も起こっていない場合の診断順序:
- 実行データの保存設定を確認。 設定 → 「成功した実行のデータを保存」はデバッグ中は「すべて」にする必要があり、「なし」ではいけません。
- 各ノードの出力を検査。 各ノードをクリック → 「出力」パネル。データが期待されるのに最初に空になっているノードを見つける。
- ピンデータ? ノードにピンアイコンがある場合、実際のデータではなく、ピン留めされたテストデータを返しています。右クリック → データのピンを解除。
- フィルター / IF 条件。
IFノードが false と評価すると、ブランチは黙ってスキップされます。実行時の条件値を確認してください。 - 認証情報のスコープ。 Google/Microsoft OAuth 認証情報はしばしばスコープが制限されています。「Google Sheets」の認証情報では Gmail を読めません。正しいスコープで再認証してください。
認証失敗
- 以前動いていたワークフローで 401 → トークンの期限切れ。認証情報を再認証してください。
- 新しいワークフローですぐに 401 → 認証情報の種類が間違っている。例:「ヘッダー認証」と「OAuth2」— API のドキュメントを確認。
- 有効なトークンで 403 → スコープ不足、またはアカウントが間違っている。OAuth 認証情報はアカウントごとに固有です。正しい Google/Meta アカウントで認証したか確認。
セルフホスト n8n 固有:コンテナ再起動後に認証情報が突然動作しなくなった場合、暗号化キー(N8N_ENCRYPTION_KEY 環境変数)が永続化されているか確認してください。失われると、すべての認証情報が破損します。
レート制限の失敗
症状:10アイテムでは成功するが、100アイテムでは失敗する。典型的なパターン。
修正パターン:
- API 呼び出しを
Split In Batchesでラップし、batchSizeをベンダーの1秒あたりの制限に合わせる - バッチ間に
Waitノードを追加:waitBetweenBatches: ceil(60000 / requests_per_minute) - HTTP Request ノードに
retry.maxTries: 3とretry.waitBetweenTries: 5000を設定 - レスポンスヘッダー(
X-RateLimit-Remaining、Retry-After)を確認し、Codeノードで動的にバックオフする
複数の Cron ジョブから同一ベンダーにアクセスする cron トリガーのワークフローの場合は、セマフォパターン(MySQL 行をロックとして使用)で API 呼び出しを1つのサブワークフローに集中化します。
サブワークフローの失敗
Execute Workflow が null や undefined を返す最も一般的な原因:
- 親がデータを渡していない。 Execute Workflow ノードの「ワークフロー入力」を確認 —
{{ $json }}または明示的なフィールドを参照している必要があります。 - 子が出力を設定していない。 サブワークフローの最後のノードの出力が戻り値になります。最後のノードが何も返さない
MySQL挿入の場合、親は何も取得しません。戻り値のペイロードを構築する最終的なSetノードを追加してください。 - 間違ったワークフロー ID。 サブワークフローが削除されて再作成された → 新しい ID → 古い参照のまま。
n8n 実行ログの読み方
実行ログはノードごとの入力と出力を表示します。デバッグパターン:
- 最初のエラーノード(赤)を見つける。
- その入力(左)を見る。期待した形状ですか?
- 入力が間違っている場合、バグは上流にあります — さかのぼって調査。
- 入力が正しいが出力が間違っている/エラーの場合、バグはこのノード内にあります — パラメータを確認。
ほとんどのバグは、下流のエラーに見せかけた上流の形状問題です。エラーメッセージはバグの実際の場所について嘘をつきます。
一般的なケースのクイックフィックスチェックリスト
- 式が補間されない → 先頭に
=を追加 - ノードが「処理するアイテムがありません」と表示 → 上流の IF ですべてフィルタリングされているか、先行ノードが空を返している
- Google Sheets の追加で重複が発生 → 一意制約がないため、べき等性チェックを追加(
mysql-checkpointingスキルを参照) - LLM がガベージ JSON を返す → 生の HTTP からスキーマ付きの
Information Extractorに切り替え(chain-llm-patternスキルを参照) - Webhook がタイムアウト → 重い処理を
Respond to Webhookの後ろに移動(先に応答し、非同期で処理)
行き詰まった場合
ユーザーに以下を依頼してください:
- 実行ログのスクリーンショット(赤い枠のパネル)
- 正確なエラーメッセージ(ノードからコピー&ペースト)
- ノードのパラメータ(設定タブ、可能であれば JSON ビュー)
- これまでに正常に動作したことがあるか(回帰か新しいバグか)
これらなしで推測しないでください。n8n のエラーは具体的です — 曖昧な推測は時間の無駄です。