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
- Open the workflow in studio, ensure the node is a Webhook trigger type, and save the draft to persist WorkflowWebhookTrigger.
- Confirm node_id matches a current webhook node via the draft graph before requesting its trigger.
- 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
- Persist the workflow draft (POST the graph) before querying a node's webhook trigger.
- Only show 'copy webhook URL' for nodes whose type is a webhook trigger.
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
- Trigger not found
- Conversation Not Exists.
- usage_invalid_flag
- usage_missing_arg
- patched environment variables require an id
AI-assisted analysis of langgenius/dify@ef8544b173 (2026-08-12).
Data as JSON: /api/errors/af84a9479b7d3c8b.
Report an issue: GitHub.