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
- If the API genuinely returns a primitive, disable 'Optimize Response' so the default optimizer stringifies it.
- Switch Response Type to 'text' to treat the body as a plain string.
- 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
- Confirm the API returns an object/array before enabling JSON optimization.
- Wrap primitive responses in an object upstream.
- Fall back to no optimization for scalar-returning endpoints.
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
- The response type must be a string. Received: ${typeof respo
- Input is not a valid JSON: ${error.message}
- Parameter ${parameter.name} is not a valid JSON: ${error.mes
- Could not replace placeholders in ${key}: ${error.message}
- The type ${genericType} is not supported
AI-assisted analysis of n8n-io/n8n@5ac6606e81 (2026-08-12).
Data as JSON: /api/errors/fd9770d8b53869e1.
Report an issue: GitHub.