n8n-io/n8n · error · NodeOperationError

There was an error: "The workflow did not return a response"

Error message

There was an error: "The workflow did not return a response"

What it means

Thrown by the Call Workflow Tool v1 after the sub-workflow executes successfully but receivedData.data[0][0].json is undefined — i.e. the sub-workflow produced no output item on its first output of its last run. The tool requires a concrete response item to hand back to the agent.

Source

Thrown at packages/@n8n/nodes-langchain/nodes/tools/ToolWorkflow/v1/ToolWorkflowV1.node.ts:139

				receivedData = await this.executeWorkflow(workflowInfo, items, runManager?.getChild(), {
					parentExecution: {
						executionId: workflowProxy.$execution.id,
						workflowId: workflowProxy.$workflow.id,
					},
					returnLastRunOnly: true, // The tool's answer is the sub-workflow's final-run output, not its internal multi-run computation.
				});
				subExecutionId = receivedData.executionId;
			} catch (error) {
				// Make sure a valid error gets returned that can by json-serialized else it will
				// not show up in the frontend
				throw new NodeOperationError(this.getNode(), error as Error);
			}

			const response: string | undefined = get(receivedData, 'data[0][0].json') as
				| string
				| undefined;
			if (response === undefined) {
				throw new NodeOperationError(
					this.getNode(),
					'There was an error: "The workflow did not return a response"',
				);
			}

			return response;
		};

		const toolHandler = async (
			query: string | IDataObject,
			runManager?: CallbackManagerForToolRun,
		): Promise<string> => {
			const { index } = this.addInputData(NodeConnectionTypes.AiTool, [[{ json: { query } }]]);

			let response: string = '';
			let executionError: ExecutionError | undefined;
			try {
				response = await runFunction(query, runManager);

View on GitHub (pinned to 5ac6606e81)

Solutions

  1. Open the sub-workflow and ensure the final node on the main output emits at least one item for the test input.
  2. Add a fallback/Set node at the end that always emits a default response item.
  3. If using a Chat Trigger sub-workflow, make sure a 'Respond to Agent' / output node is the terminal node.
  4. Check the sub-workflow execution log to see which branch produced empty output.

Example fix

// before: sub-workflow IF → empty branch → no item → tool throws
// after: add a default-branch Set node at the end:
// Set node: { response: 'No results' }
// always connected as the terminal node.
Defensive patterns

Strategy: validation

Validate before calling

const resp = get(receivedData, 'data[0][0].json');
if (resp === undefined) {
  // ensure the sub-workflow emits a default item, or surface a friendly message
  throw new Error('Sub-workflow returned no output item; add a terminal Set node');
}

Type guard

function subWorkflowReturnedData(d: ExecuteWorkflowData): boolean {
  return Array.isArray(d?.data?.[0]) && d.data[0].length > 0 && d.data[0][0]?.json !== undefined;
}

Try / catch

try { response = await runFunction(query, runManager); }
catch (e) { response = 'There was an error: ...'; /* graceful agent-facing fallback */ }

Prevention

When it happens

Trigger: The sub-workflow ends in a node that outputs nothing (e.g. an IF branch that takes the empty path, a Code node returning [], or a Stop node); the sub-workflow's last node is disabled or errored silently; the response is on a different output than output 0.

Common situations: Sub-workflow logic that conditionally produces no items; routing the real answer to a non-zero output; a sub-workflow that relies on 'Respond to Webhook' instead of returning data.

Related errors


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