n8n-io/n8n · error · NodeOperationError

The response type must be an object or an array of objects

Error message

The response type must be an object or an array of objects

What it means

Thrown by jsonOptimizer in the AI HTTP Request tool. After parsing the response (or stringifying-then-parsing), if the value is not a non-null object or array — i.e. a primitive string/number/boolean — the optimizer cannot extract fields and throws.

Source

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

		if (maxLength > 0 && text.length > maxLength) {
			return text.substring(0, maxLength);
		}

		return text;
	};
};

const jsonOptimizer = (ctx: ISupplyDataFunctions, itemIndex: number) => {
	return (response: string): string => {
		let responseData: IDataObject | IDataObject[] | string = response;

		if (typeof responseData === 'string') {
			responseData = jsonParse(response);
		}

		if (typeof responseData !== 'object' || !responseData) {
			throw new NodeOperationError(
				ctx.getNode(),
				'The response type must be an object or an array of objects',
				{ itemIndex },
			);
		}

		const dataField = ctx.getNodeParameter('dataField', itemIndex, '') as string;
		let returnData: IDataObject[] = [];

		if (!Array.isArray(responseData)) {
			if (dataField) {
				const data = responseData[dataField] as IDataObject | IDataObject[];
				if (Array.isArray(data)) {
					responseData = data;
				} else {
					responseData = [data];
				}
			} else {

View on GitHub (pinned to 5ac6606e81)

Solutions

  1. If the API genuinely returns a primitive, disable 'Optimize Response' so the default optimizer stringifies it.
  2. Switch Response Type to 'text' to treat the body as a plain string.
  3. Fix the upstream endpoint to return an object/array if JSON field extraction is required.

Example fix

// before: json optimizer against `{ "status": 200 }` is fine, but against bare `200` it throws
responseType: 'json'

// after (for a primitive-returning API):
optimizeResponse: false
Defensive patterns

Strategy: validation

Validate before calling

let parsed: unknown = typeof response === 'string' ? JSON.parse(response) : response;
if (parsed === null || (typeof parsed !== 'object' && !Array.isArray(parsed))) {
  parsed = { value: parsed }; // wrap primitives so jsonOptimizer can proceed
}

Type guard

function isJsonObjectOrArray(v: unknown): v is Record<string, unknown> | unknown[] {
  return typeof v === 'object' && v !== null;
}

Try / catch

try { return jsonOptimizer(ctx, itemIndex)(response); }
catch (e) { return defaultOptimizer(response); }

Prevention

When it happens

Trigger: Response Type 'json' selected but the API returns a bare primitive (a quoted string, a single number, true/false); the JSON parses successfully to a non-object value.

Common situations: Health-check endpoints returning 'ok' or 200; counters returning an integer; quoting/escaping that makes the body parse as a string scalar instead of an object.

Related errors


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