Merged
Size
M
Change Breakdown
Bug Fix70%
Feature20%
Maintenance10%
#27853fix(core): Add streaming keepalive to prevent proxy timeout during long agent executions

Proxy timeout errors stopped during long AI agent runs

Long-running AI agents now complete cleanly without reverse proxies injecting HTML error pages into chat streams. Three defensive layers prevent connection timeouts.

When AI agents take more than 100 seconds to complete, reverse proxies like Cloudflare terminate idle connections and inject HTML error pages into the chat stream. Users see garbled markup in their chat panels even when the agent finishes successfully.

This fix adds three layers of protection. First, socket configuration prevents TCP-level idle timeouts with the same settings already used for server-sent events. Second, a heartbeat writes a JSON keepalive chunk every 30 seconds while an execution is active, keeping the connection alive through proxies. Third, the frontend detects injected HTML error pages and replaces them with a clear user message.

The heartbeat is tied to the execution lifecycle — it starts when execution begins and stops when it finishes, so timeouts still fire independently if something hangs. The frontend parser also skips the keepalive chunks, so they don't appear as chat messages.

Users running long AI agents like Browserbase browser automation should now see clean responses instead of HTML corruption.

View Original GitHub Description

Summary

When a long-running AI Agent tool call (e.g. Browserbase browser agent ~3 min) produces no streaming chunks, reverse proxies like Cloudflare time out the idle connection (~100s) and inject a raw 524 error HTML page into the chat stream. The user sees jumbled HTML markup in the chat panel even though the agent eventually completes successfully.

This PR fixes the issue with three layers:

  1. Socket configuration (ChatTrigger.node.ts) — Apply the same socket settings the SSE push path uses (setTimeout(0), setNoDelay(true), setKeepAlive(true)) to prevent TCP-level idle timeouts.

  2. Execution-bound heartbeat (workflow-runner.ts) — Write an empty \n every 30s to the chunked response while the execution is active. The heartbeat is tied to the execution lifecycle via workflowExecuteAfter hook, so it does not outlive the execution or mask real timeouts (EXECUTIONS_TIMEOUT still fires independently). The frontend line parser already skips empty lines.

  3. Frontend HTML guard (chat message.ts) — In createLineParser(), skip non-JSON lines containing <!DOCTYPE or <html instead of rendering them as chat text. Defense-in-depth if a proxy still injects HTML despite layers 1 and 2.

How to test

  1. Set up a Chat Trigger workflow with a long-running AI Agent tool (e.g. Browserbase agent that takes >100s)
  2. Deploy behind Cloudflare or a reverse proxy with an idle timeout
  3. Send a chat message and wait for the tool to complete
  4. Verify no HTML error appears in the chat — only the agent's actual response

Related Linear tickets, Github issues, and Community forum posts

https://linear.app/n8n/issue/AI-2319

Review / Merge checklist

  • PR title and summary are descriptive. (conventions)
  • Docs updated or follow-up ticket created.
  • Tests included.
  • PR Labeled with release/backport (if the PR is an urgent fix that needs to be backported)
© 2026 · via Gitpulse