n8n の Webhook が空レスポンスになる原因と、「When Last Node Finishes」で確実にデータを返す方法
Next.js やフロントエンドアプリから n8n に Webhook でデータを送り,
n8n 側で処理して JSON で応答したい。
シンプルに見えるが、実装してみると 「n8n では結果が見えているのに、クライアントには空レスポンスしか返らない」 という現象に遭遇しやすい。
Webhook のレスポンスが正しく返らない原因と、もっとも安定したレスポンス方式についてまとめる。
Webhook ノードのレスポンスは「Respond モード」で決まる
n8n の Webhook ノードには、HTTP レスポンスの返し方に関する設定がある。
代表的なモードは以下の3つ:
- On Received
リクエストを受け取った瞬間にレスポンスを返す。
後続ノードの結果は返らない。
- When Last Node Finishes
フローの最後に実行されたノードの結果をそのままレスポンスとして返す。
- Using Respond to Webhook node
専用ノードを配置し、そこまでフローが到達した時点でレスポンスを返す。
制御が細かい反面、設定のズレでレスポンスが返らないトラブルが起きやすい。
空レスポンスが返る典型パターン
多くの場合、次のいずれかが原因:
Webhook ノードが On Received のまま
テスト URL と本番 URL を混在させている
Respond to Webhook ノードを置いたが Webhook と連動していない
Code ノードの返却形式が n8n の想定とズレている
n8n の UI 上ではデータが表示されるため気付きにくいが、
クライアント側から見ると “中身なし 200 OK” が返ってくるだけになる。
最も安定する構成:Webhook → Code →(When Last Node Finishes で返す)
レスポンスで迷子にならない方法はこれ。
- フロー構造
- Webhook
- Code
※ Respond to Webhook ノードは使わない
- Webhook の Respond
When Last Node Finishes - Webhook の Response Data
First Entry JSON
これで、最後の Code ノードの返り値がそのまま HTTP レスポンスになる。
Code ノードで返すべき形式
n8n の Code ノードは、配列の中に { json: データ } を入れて返すのがルール。
たとえば:
// Webhook 入力を取得(1件想定)
const input = $input.first().json;
// 任意の加工処理
const processed = {
/* ここに処理したデータを入れる(データ構造は自由) */
};
// 配列として返すことで Webhook がレスポンスとして認識する
return [
{
json: processed,
},
];
この “配列 + json キー” という形式を守れば、
データ内容がどんな構造でも確実に返る。
なぜ Respond to Webhook を使わない方が安定するのか?
Respond to Webhook は便利だが、以下の落とし穴がある:
- Webhook ノード側の Respond モードが一致していないと動作しない
- 複数の Respond to Webhook があると返却タイミングが曖昧になる
- 分岐や並列フローで予期せぬタイミングで返ってしまう
- テスト URL と本番 URL の挙動の差に気付きにくい
一方で Webhook → Code の 2 ノード構成は非常にシンプルで、
「最後のノード結果」=「レスポンス」という流れが明確。
API サーバのように使うなら、ほぼこの構成で足りる。
まとめ
- Webhook の Respond は When Last Node Finishes がもっとも扱いやすい
- Code ノードは 配列 + json キー の形式で返す
- データの内容(フィールド名や構造)は完全に自由
- Respond to Webhook は強力だが、レスポンス制御で迷いやすい
- Webhook → Code の構成はシンプル・安定・トラブルが少ない
n8n を「API エンドポイントのように使いたい」場合、
この構成がもっとも実用的であり、バグも起きにくい。
Discussion