Zie619/n8n-workflows · warning · Error
The JSON is not an array.
Error message
The JSON is not an array.
What it means
Produced by 'Parse and Chunk JSON Data' (workflow 1580): it takes $json.text from an lmChatOpenRouter node, strips markdown fences, JSON.parses it, and throws 'The JSON is not an array.' when the parsed value is not an Array. The surrounding try/catch converts the throw into an output item {json:{error}}, so this message typically surfaces as data flowing into 'Perform SerpAPI Search Request', not as a failed execution.
Source
Thrown at workflows/Http/1580_HTTP_Stickynote_Automate_Webhook.json:102
"credentials": {
"openRouterApi": {
"id": "WZWYWCfluxuKxZzV",
"name": "OpenRouter account"
}
},
"typeVersion": 1,
"notes": "This lmChatOpenRouter node performs automated tasks as part of the workflow."
},
{
"id": "4ab360eb-858f-48b8-a00d-71867d4f0c93",
"name": "Parse and Chunk JSON Data",
"type": "n8n-nodes-base.code",
"position": [
-1420,
160
],
"parameters": {
"jsCode": "// Parse the input JSON string and split it into four chunks\nconst rawText = $json.text;\n\n// Remove Markdown JSON code blocks if present\nconst cleanedText = rawText.replace(/```json|```/g, '').trim();\n\ntry {\n const jsonArray = JSON.parse(cleanedText);\n if (!Array.isArray(jsonArray)) {\n throw new Error('The JSON is not an array.');\n }\n const chunkSize = Math.ceil(jsonArray.length / 4);\n const chunks = [];\n for (let i = 0; i < jsonArray.length; i += chunkSize) {\n chunks.push(jsonArray.slice(i, i + chunkSize));\n }\n return chunks.map(chunk => ({ json: { chunk } }));\n} catch (error) {\n return [{ json: { error: error.message } }];\n}\n"
},
"typeVersion": 2,
"notes": "This code node performs automated tasks as part of the workflow."
},
{
"id": "5a3ac393-8355-449f-93cb-b98e8bee9b80",
"name": "Perform SerpAPI Search Request",
"type": "n8n-nodes-base.httpRequest",
"position": [
-780,
180
],
"parameters": {
"url": "{{ $env.API_BASE_URL }}",
"options": {},
"sendQuery": true,
"queryParameters": {
"parameters": [View on GitHub (pinned to 94007c1445)
Solutions
- Strengthen the LLM prompt: 'Respond with ONLY a raw JSON array, no wrapper object, no prose, no code fences.'
- Unwrap common envelope shapes before the array check (see exampleFix).
- Check the {error} output item downstream before using chunk — the SerpAPI node currently consumes it blindly as its q parameter.
- Switch the OpenRouter node to a model/params (low temperature, json/response_format if supported) that yields deterministic JSON.
Example fix
// before
const jsonArray = JSON.parse(cleanedText);
if (!Array.isArray(jsonArray)) {
throw new Error('The JSON is not an array.');
}
// after
let jsonArray = JSON.parse(cleanedText);
if (!Array.isArray(jsonArray)) {
// unwrap common LLM envelopes
const envelopeValues = Object.values(jsonArray).filter(Array.isArray);
if (envelopeValues.length === 1) jsonArray = envelopeValues[0];
else throw new Error('The JSON is not an array.');
} Defensive patterns
Strategy: validation
Validate before calling
const cleanedText = String($json.text ?? '').replace(/```json|```/g, '').trim();
let parsed = JSON.parse(cleanedText); // may throw -> caught below
if (!Array.isArray(parsed)) {
const arrays = Object.values(parsed ?? {}).filter(Array.isArray);
parsed = arrays.length === 1 ? arrays[0] : null;
}
if (!parsed) throw new Error('The JSON is not an array.'); Type guard
function isJsonArrayText(text) {
try {
return Array.isArray(JSON.parse(String(text).replace(/```json|```/g, '').trim()));
} catch { return false; }
} Prevention
- Prompt the model explicitly: 'output ONLY a raw JSON array, no wrapper object, no prose'.
- Never let the {error} item flow into the SerpAPI request unchecked — branch on json.error first.
- Prefer low temperature and structured-output settings for JSON-producing LLM calls.
When it happens
Trigger: The OpenRouter LLM returns valid JSON that is an object (e.g. {"results": [...]} or {"error": ...}) or a bare string/number instead of a top-level array. Any parse syntax error would hit the same catch but report the parser's message; this exact string means parsing succeeded and Array.isArray failed.
Common situations: Prompt does not force array-only output and the model wraps results in a key; model substitution on OpenRouter changing output style; model prefixing an apology despite instructions; temperature/settings letting the model answer in prose that happens to parse (e.g. quoted string).
Related errors
- The JSON is not an array.
- Invalid input data format
- Initial Vector 'data' is undefined or missing.
- Initial Vector 'data' is in an unsupported format.
- AES Key is missing.
AI-assisted analysis of Zie619/n8n-workflows@94007c1445 (2026-08-15).
Data as JSON: /api/errors/9c5090c11f4a7ebd.
Report an issue: GitHub.