n8n-io/n8n · error · NodeOperationError

The response type must be a string. Received: ${typeof respo

Error message

The response type must be a string. Received: ${typeof response}

What it means

Thrown by htmlOptimizer inside the AI HTTP Request tool. When 'Optimize Response' is on and 'Response Type' is 'html', the optimizer uses cheerio to parse the body, which requires a string. If the HTTP layer returned a non-string body (object, Buffer, number), this guard fires before cheerio runs.

Source

Thrown at packages/@n8n/nodes-langchain/nodes/tools/ToolHttpRequest/utils.ts:311

	const onlyContent = ctx.getNodeParameter('onlyContent', itemIndex, false) as boolean;
	let elementsToOmit: string[] = [];

	if (onlyContent) {
		const elementsToOmitUi = ctx.getNodeParameter('elementsToOmit', itemIndex, '') as
			| string
			| string[];

		if (typeof elementsToOmitUi === 'string') {
			elementsToOmit = elementsToOmitUi
				.split(',')
				.filter((s) => s)
				.map((s) => s.trim());
		}
	}

	return <T>(response: T) => {
		if (typeof response !== 'string') {
			throw new NodeOperationError(
				ctx.getNode(),
				`The response type must be a string. Received: ${typeof response}`,
				{ itemIndex },
			);
		}
		const returnData: string[] = [];

		const html = cheerio.load(response);
		const htmlElements = html(cssSelector);

		htmlElements.each((_, el) => {
			let value = html(el).html() || '';

			if (onlyContent) {
				let htmlToTextOptions;

				if (elementsToOmit?.length) {
					htmlToTextOptions = {

View on GitHub (pinned to 5ac6606e81)

Solutions

  1. Switch 'Response Type' to match the real body — 'json' for JSON APIs, 'text' for plain text.
  2. Turn off 'Optimize Response' so the default optimizer stringifies non-string bodies.
  3. Confirm the request actually returns HTML (check with a raw HTTP call) and fix the upstream URL/endpoint.

Example fix

// before: optimizer set to html but API returns JSON
responseType: 'html'

// after:
responseType: 'json'
Defensive patterns

Strategy: type-guard

Validate before calling

const body = fullResponse.body ?? fullResponse;
if (typeof body !== 'string' && responseType === 'html') {
  // coerce or switch optimizer before calling htmlOptimizer
  body = typeof body === 'object' ? JSON.stringify(body) : String(body);
}

Type guard

const isStringBody = (b: unknown): b is string => typeof b === 'string';

Try / catch

try { return htmlOptimizer(ctx, itemIndex, maxLength)(body); }
catch (e) { if (e instanceof NodeOperationError) return defaultOptimizer(body); throw e; }

Prevention

When it happens

Trigger: Selecting HTML response optimization against an API that returns JSON (parsed into an object) or binary data; setting responseType:'html' while the request option 'Response Format' causes the client to return a parsed object.

Common situations: Mismatch between the API's actual content type and the configured Response Type; a server unexpectedly returning JSON on an endpoint the user assumed was HTML; binary downloads routed through the HTML optimizer.

Related errors


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