
Step by Step Guide to solve n8n Webhook Response Error
Who this is for: n8n users who expose HTTP webhooks and need reliable 200 OK responses for external callers (APIs, browsers, or third‑party services). We cover this in detail in the n8n API Integration Errors Guide.
Quick Diagnosis
The most common cause of a webhook‑call failure is an invalid response format – e.g., wrong status code, missing Content‑Type, or a workflow that never reaches a Return node.
Quick fix
- In the Webhook node set Response Mode to “Last Node”.
- Add a Set (or Function) node that builds the JSON payload.
- Append a Return node with:
- Status Code = 200
- Content‑Type =
application/json - Body =
{{$json}}
- Save and re‑activate the workflow.
The webhook will now reply with a valid 200 OK JSON payload and the caller’s error disappears.
1. Why n8n Returns a Webhook Response Error
If you encounter any n8n conditional branch errors resolve them before continuing with the setup.
| Symptom (observed by caller) | n8n Root Cause | Typical n8n Log Message |
|---|---|---|
400 Bad Request |
No node returns a response (workflow ends without a Return node) | Webhook request received but no response was sent |
500 Internal Server Error |
Return node sends non‑JSON data while Content‑Type is application/json |
Response body does not match the declared content type |
404 Not Found |
Webhook URL typo or workflow deactivated | Webhook not found: <url> |
504 Gateway Timeout |
Long‑running async actions block the response (e.g., waiting for an external API) | Execution timed out after 30 s |
Key takeaway: n8n only sends a response when a Return node (or a node that implicitly returns, like Set with “Response Mode: Last Node”) is reached. Anything else results in the caller receiving an error.
2. Step‑by‑Step: Building a Correct Webhook Response
If you encounter any n8n batch request failure resolve them before continuing with the setup.
2.1. Basic JSON Response (most common use‑case)
Workflow shape – Webhook → Set → Return. The Return node is the last node, so its output is sent back to the caller.
2.1.1. Set node – create the payload
{
"status": "success",
"timestamp": "{{$now}}",
"data": {{$json["yourData"]}}
}
*The Set node stores this JSON in {{$json}} for the next step.*
2.1.2. Return node – configure the HTTP response
| Setting | Value |
|---|---|
| Status Code | 200 |
| Content Type | application/json |
| Body | {{$json}} |
*The Return node sends the JSON payload with a proper 200 OK status.*
2.2. Returning Plain Text or HTML
| Desired Output | Return Node Settings |
|---|---|
| Plain text | Content Type: text/plainBody: "OK" |
| HTML page | Content Type: text/htmlBody: "<h1>Success</h1>" |
2.3. Sending Custom HTTP Headers
Add a Function node before the Return node to inject a header object into the JSON payload:
// Add custom headers
items[0].json.headers = {
"X-Request-ID": $execution.id,
"Cache-Control": "no-store"
};
return items;
Map the headers in the Return node – enable “Add Headers” and set the header mapping to {{$json.headers}}.
3. Common Pitfalls & How to Avoid Them
| Pitfall | Symptom | Fix |
|---|---|---|
| No Return node | Caller receives 400/500 | End the workflow with a Return (or Set with “Last Node”). |
| Mismatched Content‑Type | 500 Internal Server Error | Ensure Content-Type matches the actual body format. |
Returning undefined |
500 error, empty response | Guard against missing fields: {{ $json.myField || "" }} |
| Large payloads (>5 MB) | 504 timeout | Enable “Response Mode: Full Response” and stream binary data, or compress JSON (zlib). |
| Async actions after Return | Caller times out before workflow finishes | Use “Execute Workflow” node after Return for background tasks. |
| CORS pre‑flight failing | Browser console shows Access-Control-Allow-Origin error |
Add header Access-Control-Allow-Origin: * (or specific origin) via Return node. |
Checklist – Before Reactivating a Webhook Workflow
- Response Mode set to “Last Node” (or “Full Response” if needed).
- Return node present and placed after all data‑preparation nodes.
- Status Code is
200 OKfor successful calls (use 4xx/5xx only for intentional error signalling). - Content‑Type matches the body (JSON →
application/json, plain text →text/plain). - No circular references in the JSON (test with
JSON.stringifyin a Function node). - Headers added via Return node are correctly mapped (no stray
nullvalues). - Workflow is active and the webhook URL matches the caller’s configuration.
4. Debugging a Failing Webhook in n8n
- Open Execution Log – click the Execution tab of the workflow to view the exact request/response payloads.
- Inspect the “Response” section – it shows the status code, headers, and body that n8n sent.
- Use the built‑in “Test Webhook” button to fire a sample request and see the live response.
- Check the server console (if self‑hosted) for stack traces that indicate serialization errors.
Example log excerpt for a mismatched Content‑Type:
[2025-12-31 14:23:07] ERROR: Response body is not a valid JSON string but Content-Type is application/json
The fix is to either change the header to text/plain or ensure the body is valid JSON.
5. Production‑Grade Considerations (EEFA)
| Concern | Why It Matters | Recommended Practice |
|---|---|---|
| Timeouts | External callers often have < 5 s limits. | Keep the webhook response under 2 s; off‑load long tasks to a separate workflow using Execute Workflow after Return. |
| Idempotency | Retries from the caller may cause duplicate side‑effects. | Return a deterministic identifier (X-Request-ID) and make downstream actions idempotent. |
| Security | Open webhook URLs can be scanned. | Restrict access with IP Whitelist or Authentication (e.g., HMAC verification) before processing. |
| Rate Limiting | High‑frequency callers can overwhelm n8n. | Add a Rate Limit node or use a reverse‑proxy (NGINX) to throttle. |
| Logging | Auditing webhook failures is essential for SLA compliance. | Enable “Log Execution Data” and ship logs to a centralized system (ELK, Loki). |
| Binary Data | Sending files requires correct Content-Type and Content‑Disposition. |
Use the Binary Data feature and set Return node to “Full Response” with appropriate headers. |
Next Steps
- Handling webhook retries with idempotent workflows – learn how to store request hashes in an n8n database.
- Securing n8n webhooks with HMAC signatures – step‑by‑step guide to verify inbound payloads.
- Streaming large files from n8n webhook responses – using binary data and
Content‑Dispositionheaders.
Implement the checklist above, re‑activate your workflow, and your webhook calls should now return clean, 200 OK responses without errors. Happy automating!



