Skip to content
Skip to main content
n8n, Slack and Stripe logo tiles over a brass stopwatch and a coiled orange network cable on a green desk mat — the callers that time out when an n8n Respond to Webhook node answers too late
8 min readBy Carlos Aragon

n8n Respond to Webhook: Timeouts and Empty Replies

An n8n Respond to Webhook node can only answer while the caller's HTTP connection is still open, so most “timeouts” are the caller giving up, not n8n. The fix is to respond first and work second. Two other failures look like timeouts but aren't: a branch that skips the response node gets an empty 200, and an error before it gets a generic 500. I tested all three on a live n8n 2.38.3 instance this morning, and the numbers are below.

What Does n8n Actually Return in Each Case?

I built a throwaway workflow on my self-hosted n8n: a Webhook node set to respond “Using Respond to Webhook Node”, a Code node that throws on ?err=1, an IF that sends ?skip=1 down a branch with no response node, and a normal path that responds with {"ok":true} and then waits 4 seconds. Then I hit it with curl.

ScenarioWhat the caller gotTime
Respond first, then Wait 4 s200, {"ok":true}0.094 s
Branch never reaches the response node200, empty body0.057 s
Code node throws before responding500, {"message":"Error in workflow"}0.023 s
Wait 70 s, then respond (local)200, {"ok":true}70.1 s
Wait 110 s, then respond (via Cloudflare tunnel)200, {"ok":true}110.2 s

The first row is the whole post in one line: the workflow kept running for four more seconds, and the caller didn't care, because it already had its answer. Respond to Webhook sends the response when it runs, not when the execution ends.

Is n8n Timing Out, or Is the Caller?

Almost always the caller. The last two rows surprised me. You'll find old forum threads saying a Wait over 65 seconds before the response node breaks the reply, because n8n offloads long waits to the database. On 2.38.3 it didn't: 70 seconds answered fine locally, and 110 seconds answered through the Cloudflare tunnel that fronts my instance. So I'd stop blaming n8n first.

The clock that matters belongs to whoever sent the request. Slack gives interactive payloads and slash commands 3 seconds to acknowledge. Twilio waits 15 seconds by default. Payment and CRM webhooks usually allow somewhere between 10 and 30 seconds, then mark the delivery failed and retry. Put an LLM call in front of your response node and you've spent that budget before the model has finished thinking.

And a retry is worse than a timeout. The caller gives up, n8n keeps running, and then the caller sends the same event again. Now you have two executions doing the same work. I wrote up how to guard against that in n8n duplicate executions and idempotency. Your budget is the sender's timeout minus network time, and it's usually small.

Why Does My n8n Webhook Return an Empty Body?

This is the one I'd call a trap. When the Webhook node is set to wait for a Respond to Webhook node and the execution ends without ever running one, n8n still closes the request with a 200 and nothing in it. No error, no warning in the execution list. The execution shows as successful, because from n8n's side it was.

The usual cause is an IF or Switch where only the happy path has a response node. A form posts a lead with a missing email, the IF routes it to the “false” branch, and the front end gets a 200 it reads as “saved”. I found one of these in a client lead-capture flow where the rejection branch had been added months after the original build. Nobody noticed because nothing failed.

The other causes I've seen:

  • A node returns zero items. A filter, a lookup with no match, or a Code node returning []stops that branch. Nothing downstream runs, including your response node. Turn on “Always Output Data” on the node that can come back empty, or handle the empty case explicitly.
  • Respond With is set wrong.“First Incoming Item” on an item with no JSON, or “No Data” left over from testing, gives a legitimately empty response.
  • You're on the test URL. The /webhook-test/URL only listens while you click “Listen for test event”. Production callers must use /webhook/, and the workflow must be published.

Rule: every branch that can end an execution ends in a Respond to Webhook node. Rejection branches get a 400 with a reason. It takes five minutes and turns a silent success into an error the front end can show.

What Happens When the Workflow Errors Before Responding?

You get a 500 with {"message":"Error in workflow"}. That matches the n8n docs, and it's honest, but it's useless to the caller. Your real error message stays inside n8n.

If the caller needs to know what went wrong, don't let the error escape. On the risky node, set On Error to “Continue (using error output)” and wire that output to its own Respond to Webhook node with a 502 or 422 and a short message. Keep the error workflow too, for alerting. I covered the cases where it silently doesn't fire in why the n8n error workflow isn't triggering.

One more rule from the docs that bites people who add a second response node “just in case”: only the first Respond to Webhook node that executes is used. A second one that runs later is ignored. So you can't send an ack and then a final result on the same request. That needs a second channel.

How Do You Fix It? The Ack-First Pattern

Every webhook workflow I build now has the same shape. The response goes out before anything slow happens:

Webhook (Respond: Using 'Respond to Webhook' Node)
  -> Validate (IF: signature, required fields)
       true  -> Respond to Webhook  (202, {"accepted": true, "id": "{{ $execution.id }}"})
                  -> AI Agent / HTTP calls / DB writes   (as slow as it needs)
                  -> Deliver result (callback URL, Slack response_url, DB row)
       false -> Respond to Webhook  (400, {"error": "missing email"})

Why each piece is there:

  • Validate before you ack.Checking a signature or a required field takes milliseconds, and it means a 202 actually means “I have what I need”. Acking garbage and failing later is how you lose leads quietly.
  • Return an ID. The execution ID or your own job ID lets the caller, or you, find the run later.
  • Deliver the result out of band. Slack gives you a response_url for exactly this. For your own front end, write the result to a table and let the page poll a second small webhook, or push it over a callback URL.

If you don't need to send anything custom back, there's a shortcut: set the Webhook node's Respond option to “Immediately”. n8n answers at once with “Workflow got started” and you skip the response node entirely. It's the right choice for fire-and-forget events like Stripe or CRM notifications, where the sender only wants a 2xx.

For a chat UI where the user is watching, the Webhook node also has a “Streaming” response mode that sends tokens as the AI Agent produces them. It has its own ways to go wrong, which I went through in n8n AI Agent streaming not working. Immediately for events, ack-first for anything that needs a real answer, streaming for chat.

What About Proxies, Tunnels and Queue Mode?

Anything between the caller and n8n can set its own limit. Cloudflare documents a 524 error when an origin takes longer than 100 seconds on a proxied request. My tunnel-fronted instance answered at 110 seconds anyway, so don't treat that number as gospel for tunnels, but do test your own path. Nginx's default proxy_read_timeout is 60 seconds, which is a common reason a self-hosted setup cuts off at exactly one minute. If you protect webhooks with Cloudflare Access, the setup is in Cloudflare Access for n8n webhooks.

In queue mode, the webhook process holds the connection while a worker runs the execution. Ack-first matters more there: if the workers are all busy, the job waits in Redis while the caller's clock keeps running. A fast response node doesn't help if the execution hasn't started yet, so keep enough worker concurrency for your webhook traffic, or use Respond: Immediately for events that can wait.

Raising timeouts is the last thing I'd do, not the first. You can make every hop wait longer, but you can't change Slack's 3 seconds. Moving the response node fixes it for every caller at once.

Webhooks Dropping Leads or Double-Firing?

I build and fix n8n workflows that sit behind forms, CRMs, payment providers and AI agents, with responses that go out on time and retries that don't create duplicates. Tell me what's calling your webhook and what's going wrong.

Response codes, bodies and timings measured 28 September 2026 with curl against a self-hosted n8n 2.38.3 (Docker) on a test workflow that was deleted afterwards. Respond to Webhook behavior (first node wins, 500 on error) and the Webhook node's Respond options checked against the n8n docs the same day.

Related Posts