How to Fix n8n Respond to Webhook Not Working and Return Custom Error Responses

What broke

You wire up a Respond to Webhook node with a JSON body and a 400 status code, call the webhook, and get back an empty 200. Or your error branch never answers and the caller times out. The node looks broken, but it never ran.

Quick answer: Set the Webhook trigger’s Respond option to “Using ‘Respond to Webhook’ node”, then add a Respond to Webhook node with Respond With set to JSON and a Response Code. If the trigger still answers Immediately, your custom response never runs.

The hard part is not the Respond to Webhook node, it is the Webhook trigger’s Respond setting, which defaults to Immediately and silently answers before your node ever runs.

Checked on 2026-11-14 against the official Respond to Webhook docs and Webhook node docs. New to webhooks? The complete n8n guide covers trigger setup.

n8n Respond to Webhook documentation page

The official Respond to Webhook docs, checked 2026-11-14.

n8n has more than 210,000 stars on GitHub as of November 2026, and webhooks are how most users turn a workflow into an API. The official docs state plainly: “The workflow errors before the first Respond to Webhook node executes: the workflow returns an error message with a 500 status.” The same page adds two rules that explain most empty responses: the node “runs once, using the first incoming data item”, and a second Respond to Webhook node after the first one is ignored. If webhooks are new to you, the complete n8n guide covers the trigger setup this fix builds on.

The fix

  1. Open the Webhook trigger node. Change Respond from Immediately to Using ‘Respond to Webhook’ node. Save the workflow and re-activate it. The Production URL works only while active.
  2. Add a Respond to Webhook node after the nodes whose data you want to return. The official Respond to Webhook documentation lists every Respond With option, including JSON, Text, Redirect, and No Data.
  3. Set Respond With to JSON and put your body in Response Body as an expression:
={{ { error: "missing order_id", code: "VALIDATION_FAILED" } }}
  1. Under Add Option, set Response Code to 400 for bad input or 500 for a server failure, and add a Response Headers entry of Content-Type: application/json.
  2. For the error path, put an IF node before the response: valid input goes to a success Respond node returning 200, invalid input to the error Respond node returning 400. Only one Respond node runs per execution, so one per branch is safe.
  3. To return a custom error when a node itself throws, open that node’s Settings tab, set On Error to Continue (using error output), and connect its error output to a Respond to Webhook node with your own error JSON. Without this, n8n answers with its own 500. The n8n error handling tutorial covers retries and error workflows, and the official Webhook node documentation documents the Respond modes.

Pitfalls that make the fix look like it failed

PitfallWhat you seeFix
Trigger still on ImmediatelyEmpty 200, Respond node never runsChange the trigger’s Respond setting, save, re-activate
Test URL already used once404 “webhook not registered”Test listeners accept one call, then expire. Click Execute workflow again, or use Production URL
Expression resolves to nothing200 with an empty bodyTurn on Enable Response Output Branch in the node’s Settings tab to see what was sent
Second Respond node runsSilently ignored, only the first countsUse one Respond node per branch, or merge branches before a shared node
Slow work before the Respond nodeCaller times out, often around two minutesAnswer early with a 202 Accepted Respond node after validation, then keep working
Text response renders as a pageHTML shows inside a sandboxed frameText sends Content-Type text/html, and since n8n 1.103.0 HTML is wrapped in an iframe. Use JSON for API callers

How to verify the fix

Call the Production URL with curl and read the status line. Example, replace with your values:

curl -i -X POST https://your-n8n.example.com/webhook/orders \
  -H 'Content-Type: application/json' \
  -d '{"order_id": ""}'

A fixed workflow answers HTTP/1.1 400 with the body {"error": "missing order_id", "code": "VALIDATION_FAILED"}. Then send a valid order_id and confirm the success path answers 200. If you still get an empty 200, re-check the trigger’s Respond setting. A related failure has a different cause: fixing n8n webhook not registered 404 errors behind a reverse proxy.

When this article does not apply

To return more than one data item, use an Aggregate node to merge items into one, or set the trigger to When Last Node Finishes. If the same workflow is also called as a sub-workflow, Respond to Webhook throws “No Webhook node found in the workflow”, so use When Last Node Finishes instead. For streaming responses, use the Streaming response mode instead.

Test before you rely on it: send one invalid request and confirm the 400 body, send one valid request and confirm the 200 body, trigger a real node error and confirm your custom error JSON comes back, and call the Production URL twice.

Frequently asked questions

Why does my Respond to Webhook node return an empty 200?

The Webhook trigger's Respond option is still set to Immediately, its default. That mode answers with an empty 200 the instant the webhook fires, so your Respond to Webhook node never runs. Change Respond to Using 'Respond to Webhook' node, save, and re-activate the workflow.

Can I return a custom 500 error instead of n8n's default error message?

Yes. Open the risky node's Settings tab, set On Error to Continue (using error output), and connect its error output to a Respond to Webhook node that returns your own JSON body with the status code you choose.

Why does the caller time out even though the workflow succeeds?

The Respond to Webhook node sits after slow work, so the caller waits and gives up. Put a Respond to Webhook node right after validation that answers 202 Accepted, then let the rest of the workflow run after it.

Does Respond to Webhook work with the Test URL?

Yes, while the workflow is listening for a test event, but a test listener accepts only one call and then expires. For repeatable calls, activate the workflow and use the Production URL.

TP
ToolPilot Team

We install, break, and fix automation tools so you don't have to. Every tutorial on ToolPilot is tested hands-on before publishing.

Keep reading