n8n-io/n8n · error · NodeOperationError
Wrong output type returned
Error message
Wrong output type returned
What it means
Thrown by WorkflowToolService.handleToolResponse (v2) when the sub-workflow response is not a number, not an INodeExecutionData[], not an object, and not a string — i.e. it is a boolean, function, symbol, bigint, or similar. The tool must serialize the response to a string for the agent, and it has no serializer for these types.
Source
Thrown at packages/@n8n/nodes-langchain/nodes/tools/ToolWorkflow/v2/utils/WorkflowToolService.ts:245
private handleToolResponse(response: unknown): string {
if (typeof response === 'number') {
return response.toString();
}
if (isNodeExecutionData(response)) {
return JSON.stringify(
response.map((item) => item.json),
null,
2,
);
}
if (isObject(response)) {
return JSON.stringify(response, null, 2);
}
if (typeof response !== 'string') {
throw new NodeOperationError(this.baseContext.getNode(), 'Wrong output type returned', {
description: `The response property should be a string, but it is an ${typeof response}`,
});
}
return response;
}
/**
* Executes specified sub-workflow with provided inputs
*/
private async executeSubWorkflow(
context: ISupplyDataFunctions | IExecuteFunctions,
workflowInfo: IExecuteWorkflowInfo,
items: INodeExecutionData[],
workflowProxy: IWorkflowDataProxyData,
runManager?: CallbackManagerForToolRun,
): Promise<{ response: IDataObject | INodeExecutionData[]; subExecutionId: string }> {
let receivedData: ExecuteWorkflowData;View on GitHub (pinned to 5ac6606e81)
Solutions
- In the sub-workflow, convert the final value to a string or object before the terminal node (e.g. a Set node with String(value)).
- Ensure the terminal node always emits a plain JSON-shaped item (string/number/object/array).
- If returning all items, make sure the output is an array of { json: ... } items.
Example fix
// before: sub-workflow returns { json: { result: true } } and only `true` is read → boolean → throws
// after: wrap it
{ json: { response: 'Yes' } }
// or stringify in a Code node: return [{ json: { response: String(items[0].json.flag) } }]; Defensive patterns
Strategy: type-guard
Validate before calling
if (typeof response !== 'string' && typeof response !== 'number' && !isObject(response) && !isNodeExecutionData(response)) {
response = String(response); // coerce before handleToolResponse
} Type guard
function isToolSerializable(v: unknown): v is string | number | object | INodeExecutionData[] {
return ['string','number','object'].includes(typeof v) && v !== null;
} Try / catch
try { return this.handleToolResponse(response); }
catch (e) { return String(response); } Prevention
- Make sub-workflow terminal nodes emit string/number/object/array payloads only.
- Avoid returning bare booleans/bigints from Code nodes.
- Add a final Set node that normalizes the output shape.
When it happens
Trigger: A sub-workflow whose terminal node returns a boolean or bigint as the json value; returnAllItems=true with a non-array, non-object payload; an edge case where the response is a function/symbol from a misbehaving custom node.
Common situations: Sub-workflows returning a bare boolean (true/false) as the answer; numeric/bigint counters; exotic types produced by Code nodes that return non-JSON values.
Related errors
- The response type must be a string. Received: ${typeof respo
- The provided workflow is not valid JSON: "${(error as Error)
- There was an error: "The workflow did not return a response"
- Error during parsing of JSON Schema. ${error}
- There was an error: "The workflow did not return a response"
AI-assisted analysis of n8n-io/n8n@5ac6606e81 (2026-08-12).
Data as JSON: /api/errors/38e0351b03ef4f78.
Report an issue: GitHub.