n8n-io/n8n · error · NodeOperationError

Workflow must be started from a chat trigger node

Error message

Workflow must be started from a chat trigger node

What it means

Thrown by the ChatTrigger-adjacent response/agent node's execute() when no enabled Chat Trigger node can be found — neither among the parent nodes nor via getChatTrigger() (the tool-mode fallback). The response path is only valid inside a chat-triggered workflow.

Source

Thrown at packages/@n8n/nodes-langchain/nodes/trigger/ChatTrigger/Chat.node.ts:347

	async execute(this: IExecuteFunctions): Promise<INodeExecutionData[][]> {
		const connectedNodes = this.getParentNodes(this.getNode().name, {
			includeNodeParameters: true,
		});

		let chatTrigger: INode | NodeTypeAndVersion | undefined | null = connectedNodes.find(
			(node) => node.type === CHAT_TRIGGER_NODE_TYPE && !node.disabled,
		);

		if (!chatTrigger) {
			try {
				// try to get chat trigger from workflow if node working as a tool
				chatTrigger = this.getChatTrigger();
			} catch (error) {}
		}

		if (!chatTrigger) {
			throw new NodeOperationError(
				this.getNode(),
				'Workflow must be started from a chat trigger node',
			);
		}

		const parameters = chatTrigger.parameters as {
			mode?: 'hostedChat' | 'webhook';
			options: { responseMode: 'lastNode' | 'responseNodes' | 'streaming' | 'responseNode' };
		};

		if (parameters.mode === 'webhook') {
			throw new NodeOperationError(
				this.getNode(),
				'"Embedded chat" is not supported, change the "Mode" in the chat trigger node to the "Hosted Chat"',
			);
		}

		if (parameters.options.responseMode !== 'responseNodes') {

View on GitHub (pinned to 5ac6606e81)

Solutions

  1. Add a Chat Trigger node as the workflow's trigger and connect it upstream of this node.
  2. Re-enable the existing Chat Trigger if it was disabled.
  3. Reconnect this node so it is a descendant of the Chat Trigger (or used as a tool with getChatTrigger()).
  4. If you don't need chat, remove this node and use a standard output.

Example fix

// before: Schedule Trigger → AI Agent (no Chat Trigger) → throws
// after: Chat Trigger → AI Agent → this node
// (replace the trigger, or wire a Chat Trigger as the entry point)
Defensive patterns

Strategy: validation

Validate before calling

const connected = this.getParentNodes(this.getNode().name, { includeNodeParameters: true });
const hasChatTrigger = connected.some(n => n.type === CHAT_TRIGGER_NODE_TYPE && !n.disabled);
if (!hasChatTrigger) throw new Error('Connect a Chat Trigger upstream');

Type guard

function isChatTrigger(node: INode | NodeTypeAndVersion): boolean {
  return (node as INode).type === CHAT_TRIGGER_NODE_TYPE && !(node as INode).disabled;
}

Prevention

When it happens

Trigger: Adding an AI response/agent node to a workflow that is triggered by a non-chat trigger (Webhook, Schedule, Manual, Form); the Chat Trigger exists but is disabled; the Chat Trigger is not an upstream parent of this node.

Common situations: Building a chat flow then swapping the trigger type; disabling the Chat Trigger for testing; wiring the response node into a branch that isn't downstream of the Chat Trigger.

Related errors


AI-assisted analysis of n8n-io/n8n@5ac6606e81 (2026-08-12). Data as JSON: /api/errors/9def120959ab5aaa. Report an issue: GitHub.