n8n - 💡(How to fix) Fix Webhook 404 after publish/restart + crash "Cannot read properties of undefined (reading 'node')" in webhook handler [1 comments, 2 participants]

Official PRs (…)
ON THIS PAGE

Recommended Tools

×6

Utilities matched from this issue’s tags and category — try them while you read without losing context.

GitHub issue graph ai analysis

Paste a GitHub issue URL. We fetch that issue, discover linked issues from bodies/comments/timeline, collect linked pull requests, and produce a structured English report.

The report is written in English Markdown for sharing and archival.

Helpful · Quick feedback

Loading…
GitHub stats
n8n-io/n8n#28373Fetched 2026-04-13 05:45:22
View on GitHub
Comments
1
Participants
2
Timeline
4
Reactions
0
Author
Timeline (top)
commented ×1labeled ×1mentioned ×1subscribed ×1

Error Message

Error in handling webhook request GET /webhook/confirmar-recebimento:

Root Cause

Root cause:

Fix Action

Fix / Workaround

Workaround Attempted

Code Example

workflowId/encodedNodeName/path

---

path  (e.g. "confirmar-recebimento")

---

"24i838wUhoWwTv0x/webhook%20confirmar%20recebimento/confirmar-recebimento" | GET | pathLength=2
"oT9cVcSYc1X37d9x/webhook%20pagamento/pagar-reembolso"                     | GET | pathLength=2

---

Received request for unknown webhook: The requested webhook 
"GET 24i838wUhoWwTv0x/webhook confirmar recebimento/confirmar-recebimento" is not registered.

---

Error in handling webhook request GET /webhook/confirmar-recebimento: 
Cannot read properties of undefined (reading 'node')

---

Received request for unknown webhook: The requested webhook "GET confirmar-recebimento" is not registered.
RAW_BUFFERClick to expand / collapse

Environment

  • n8n version: 2.13.3
  • Deployment: Docker Swarm (via Easypanel), self-hosted
  • Database: PostgreSQL
  • Node type: n8n-nodes-base.webhook, typeVersion: 2

Bug Description

Two related issues that together cause webhook nodes to permanently return 404, even on Published/active workflows.


Bug 1 — Stale webhook_entity rows block re-registration after webhookId is assigned

Root cause:

When a Webhook node has no webhookId set, getNodeWebhookPath() in node-helpers.js generates a long-path URL:

workflowId/encodedNodeName/path

For example: 24i838wUhoWwTv0x/webhook%20confirmar%20recebimento/confirmar-recebimento

When webhookId is later set on the node (e.g., after editing and saving the workflow), getNodeWebhookPath() now generates a short-path URL:

path  (e.g. "confirmar-recebimento")

However, WebhookService.registerWebhook() uses UPSERT ... ON CONFLICT (method, webhookPath). Since the new short-path and the old long-path are different strings, the old row is never deleted. Both rows coexist in webhook_entity.

The old long-path rows have pathLength > 0 (treated as "dynamic" webhooks). populateCache() at startup only loads pathLength === 0 rows into the in-memory handler map. The short-path rows — if ever inserted — have pathLength === 0 and would work.

Evidence from webhook_entity (before fix):

"24i838wUhoWwTv0x/webhook%20confirmar%20recebimento/confirmar-recebimento" | GET | pathLength=2
"oT9cVcSYc1X37d9x/webhook%20pagamento/pagar-reembolso"                     | GET | pathLength=2

These stale rows persist through restarts, deploys, and workflow deactivation/reactivation cycles. Even after deleting them and restarting n8n, Bug 2 (below) prevents correct re-registration.

Logs confirming the long-path format:

Received request for unknown webhook: The requested webhook 
"GET 24i838wUhoWwTv0x/webhook confirmar recebimento/confirmar-recebimento" is not registered.

Bug 2 — Runtime crash: Cannot read properties of undefined (reading 'node')

Even after manually deleting the stale rows, restarting n8n, and republishing the workflow, webhooks still return 404.

n8n server logs show:

Error in handling webhook request GET /webhook/confirmar-recebimento: 
Cannot read properties of undefined (reading 'node')

This crash occurs during webhook request handling, after the path is found in the initial registry lookup (i.e., the webhook IS registered in webhook_entity / in memory), but something is undefined when n8n attempts to access the .node property of the execution context or webhook data object.

After this crash, subsequent requests from the same instance return:

Received request for unknown webhook: The requested webhook "GET confirmar-recebimento" is not registered.

This suggests the crash corrupts or prevents the in-memory handler from being properly established, causing the webhook to effectively disappear from the in-memory registry.


Steps to Reproduce

  1. Create a workflow with a Webhook node. At this point the node has no webhookId set.
  2. Activate the workflow. n8n registers a long-path webhook in webhook_entity: workflowId/encodedNodeName/path.
  3. Edit and save the workflow (or perform any action that causes n8n to assign a webhookId to the node).
  4. Deactivate and reactivate the workflow, OR restart n8n.
  5. n8n attempts to register the short-path webhook (path only), but:
    • The old long-path row is NOT removed from webhook_entity
    • The new short-path may not be inserted at all due to Bug 2
  6. All requests to /webhook/{path} return 404 indefinitely.

Expected Behavior

  • When a Webhook node's webhookId is set (and isFullPath: true in the webhook description), the short-path URL should be the only registration in webhook_entity.
  • On workflow activation, any stale rows for the same workflow+node combination but with a different path format should be deleted.
  • Webhook requests should be handled successfully without a TypeError crash.

Actual Behavior

  • Stale long-path rows in webhook_entity persist indefinitely.
  • After fixing the stale rows manually, a TypeError: Cannot read properties of undefined (reading 'node') crash occurs during webhook request handling.
  • Affected webhooks return 404 even though the workflow is Published/active and the n8n UI shows the correct production URL.

Workaround Attempted

  1. Manually deleted stale rows from webhook_entity via psql: DELETE FROM webhook_entity WHERE "workflowId" IN ('...', '...')
  2. Restarted n8n: docker service update --force n8n_n8n
  3. Unpublished and republished the workflow via the n8n UI

None of these resolved the issue. The crash in Bug 2 persists across all restarts.


Relevant Code

  • n8n-workflow/src/node-helpers.tsgetNodeWebhookPath(): Does not generate the short path when node.webhookId === undefined, regardless of isFullPath.
  • packages/cli/src/webhooks/webhook.service.tsregisterWebhook(): Uses UPSERT on (method, webhookPath) — does not delete old rows with different paths for the same node.
  • packages/cli/src/webhooks/webhook.service.ts → somewhere in the request handling path: crashes with TypeError: Cannot read properties of undefined (reading 'node').

extent analysis

TL;DR

  • The most likely fix involves modifying the registerWebhook function to properly handle and remove stale webhook entries and addressing the TypeError crash during request handling by ensuring the node property is defined.

Guidance

  1. Modify registerWebhook to handle stale entries: Update the registerWebhook function in webhook.service.ts to delete old rows with different paths for the same node before inserting a new row. This can be achieved by first querying for existing rows that match the workflow and node, and then deleting them if their path does not match the new path.
  2. Fix getNodeWebhookPath to generate short paths correctly: Ensure getNodeWebhookPath in node-helpers.ts generates the short path when isFullPath is true, regardless of node.webhookId.
  3. Address the TypeError crash: Identify where the TypeError: Cannot read properties of undefined (reading 'node') occurs in the request handling path and ensure that the node property is defined before accessing it. This might involve checking for null or undefined values before attempting to access properties.
  4. Verify database consistency: After applying fixes, manually verify that webhook_entity does not contain stale rows and that new webhooks are registered correctly.

Example

// Example of how registerWebhook could be modified to handle stale entries
async function registerWebhook(webhook: WebhookEntity) {
  // First, delete any existing stale rows for the same workflow and node
  await deleteStaleWebhooks(webhook.workflowId, webhook.nodeId, webhook.webhookPath);
  
  // Then, insert the new webhook row
  await this.db.query(`UPSERT INTO webhook_entity (method, webhookPath) VALUES ($1, $2)`, [webhook.method, webhook.webhookPath]);
}

async function deleteStaleWebhooks(workflowId: string, nodeId: string, newWebhookPath: string) {
  await this.db.query(`DELETE FROM webhook_entity WHERE workflowId = $1 AND nodeId = $2 AND webhookPath != $3`, [workflowId, nodeId, newWebhookPath]);
}

Notes

  • The provided example is a simplified illustration and may need adjustments based on the actual database schema and the webhook.service.ts implementation.
  • Ensuring the node property is defined before accessing it is crucial to prevent the TypeError crash.

Recommendation

  • Apply the workaround by modifying the registerWebhook function and ensuring the node property is defined, as these changes directly address the identified issues.

FAIL-SAFE

Given the complexity of the issue and the need for precise modifications to the codebase, it's essential to thoroughly test any changes in a non-production environment before deploying them to prevent unintended consequences.

Vote matrix · Quick signals

Works
Did the solution work? Tap to confirm.
Easy Fix
Was it a quick fix?
Time Saver
Did it save you time?
Blocking
Was it severely blocking?
Common Issue
Are others likely hitting this too?
Flaky / Intermittent
Is it intermittent?
Verified / Reproducible
Can you reproduce it reliably?
Loading…

Still need to ship something?

×6

Another batch ranked right after the header list — different links, same matching logic.

Back to top recommendations

TRENDING