langgenius/dify · error · NotFound

Webhook trigger not found for this node

Error message

Webhook trigger not found for this node

What it means

Raised by GET /apps/{app_id}/workflows/webhook/trigger?node_id=... when no WorkflowWebhookTrigger row matches (app_id, node_id). The node either is not a webhook trigger node or has never had its trigger persisted. Returned via flask_restx NotFound (HTTP 404).

Source

Thrown at api/controllers/console/app/workflow_trigger.py:123

    @model_validate(Parser)
    def get(self, req_data: Parser, app_model: App):
        """Get webhook trigger for a node"""

        node_id = req_data.node_id

        with sessionmaker(db.engine, expire_on_commit=False).begin() as session:
            # Get webhook trigger for this app and node
            webhook_trigger = session.scalar(
                select(WorkflowWebhookTrigger)
                .where(
                    WorkflowWebhookTrigger.app_id == app_model.id,
                    WorkflowWebhookTrigger.node_id == node_id,
                )
                .limit(1)
            )

            if not webhook_trigger:
                raise NotFound("Webhook trigger not found for this node")

            return dump_response(WebhookTriggerResponse, webhook_trigger)


@console_ns.route("/apps/<uuid:app_id>/triggers")
class AppTriggersApi(Resource):
    """App Triggers list API"""

    @setup_required
    @login_required
    @account_initialization_required
    @console_ns.response(200, "Success", console_ns.models[WorkflowTriggerListResponse.__name__])
    @with_current_tenant_id
    @rbac_permission_required(RBACResourceScope.APP, RBACPermission.APP_VIEW_LAYOUT)
    @get_app_model(mode=AppMode.WORKFLOW)
    def get(self, current_tenant_id: str, app_model: App):
        """Get app triggers list"""
        with sessionmaker(db.engine, expire_on_commit=False).begin() as session:

View on GitHub (pinned to ef8544b173)

Solutions

  1. Open the workflow in studio, ensure the node is a Webhook trigger type, and save the draft to persist WorkflowWebhookTrigger.
  2. Confirm node_id matches a current webhook node via the draft graph before requesting its trigger.
  3. Verify the app mode is WORKFLOW (the route is gated by @get_app_model(mode=AppMode.WORKFLOW)).
Defensive patterns

Strategy: validation

Validate before calling

const draft = await get(`/apps/${appId}/workflows/draft`);
const node = draft.graph.nodes.find(n => n.id === nodeId);
if (!node || node.type !== 'webhook-trigger') { /* do not request webhook trigger */ }

Try / catch

try {
  await get(`/apps/${appId}/workflows/webhook/trigger`, { params: { node_id: nodeId } });
} catch (e) {
  if (e.code === 404 && /webhook trigger not found/i.test(e.message)) {
    // prompt to save the draft with a webhook node present
  } else { throw e; }
}

Prevention

When it happens

Trigger: GET /console/api/apps/{app_id}/workflows/webhook/trigger?node_id=<id> where node_id is not a webhook node, was deleted from the draft, or its trigger row was never created on save.

Common situations: Querying a webhook URL before saving the workflow draft; node_id from a copied graph that was never persisted; node was changed to a different type after the trigger was created; querying for a node in an app that is not in WORKFLOW mode.

Related errors


AI-assisted analysis of langgenius/dify@ef8544b173 (2026-08-12). Data as JSON: /api/errors/af84a9479b7d3c8b. Report an issue: GitHub.