{"record":{"id":"a13353db24a87d43","repo":"Zie619/n8n-workflows","slug":"the-json-is-not-an-array-a13353","errorCode":null,"errorMessage":"The JSON is not an array.","messagePattern":"The JSON is not an array\\.","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"warning","filePath":"workflows/Http/1747_HTTP_Stickynote_Automate_Webhook.json","lineNumber":102,"sourceCode":"      \"credentials\": {\n        \"openRouterApi\": {\n          \"id\": \"WZWYWCfluxuKxZzV\",\n          \"name\": \"OpenRouter account\"\n        }\n      },\n      \"typeVersion\": 1,\n      \"notes\": \"This lmChatOpenRouter node performs automated tasks as part of the workflow.\"\n    },\n    {\n      \"id\": \"4ab360eb-858f-48b8-a00d-71867d4f0c93\",\n      \"name\": \"Parse and Chunk JSON Data\",\n      \"type\": \"n8n-nodes-base.code\",\n      \"position\": [\n        -1420,\n        160\n      ],\n      \"parameters\": {\n        \"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\"\n      },\n      \"typeVersion\": 2,\n      \"notes\": \"This code node performs automated tasks as part of the workflow.\"\n    },\n    {\n      \"id\": \"5a3ac393-8355-449f-93cb-b98e8bee9b80\",\n      \"name\": \"Perform SerpAPI Search Request\",\n      \"type\": \"n8n-nodes-base.httpRequest\",\n      \"position\": [\n        -780,\n        180\n      ],\n      \"parameters\": {\n        \"url\": \"{{ $env.API_BASE_URL }}\",\n        \"options\": {},\n        \"sendQuery\": true,\n        \"queryParameters\": {\n          \"parameters\": [","sourceCodeStart":84,"sourceCodeEnd":120,"githubUrl":"https://github.com/Zie619/n8n-workflows/blob/94007c1445d9258a7da116646b79473e7c7c3282/workflows/Http/1747_HTTP_Stickynote_Automate_Webhook.json#L84-L120","documentation":"Same 'Parse and Chunk JSON Data' node replicated in workflow 1747. It throws 'The JSON is not an array.' when the LLM text parses to a non-array JSON value; the catch then returns [{json:{error}}], so the message usually travels as data into the downstream SerpAPI request rather than failing the execution.","triggerScenarios":"The lmChatOpenRouter node returns a JSON object (results wrapper, error object) or scalar instead of a top-level array, and Array.isArray(jsonArray) is false after successful JSON.parse.","commonSituations":"Prompt asks for 'JSON' but not specifically an array; different OpenRouter model honoring the format differently; the two workflows drifting so 1747's prompt is weaker than 1580's; long outputs getting truncated into a valid-but-wrong shape.","solutions":["Make the upstream prompt demand a top-level JSON array only (no object wrapper, no commentary).","Add envelope unwrapping before the Array.isArray check (see exampleFix).","Branch on the error item downstream so a bad LLM reply cannot become a SerpAPI query.","Pin a known-good LLM response for testing the chunking logic in isolation."],"exampleFix":"// before\nconst jsonArray = JSON.parse(cleanedText);\nif (!Array.isArray(jsonArray)) {\n    throw new Error('The JSON is not an array.');\n}\n\n// after\nlet parsed = JSON.parse(cleanedText);\nif (parsed && !Array.isArray(parsed) && typeof parsed === 'object') {\n  const arrays = Object.values(parsed).filter(Array.isArray);\n  if (arrays.length === 1) parsed = arrays[0];\n}\nif (!Array.isArray(parsed)) {\n    throw new Error('The JSON is not an array.');\n}\nconst jsonArray = parsed;","handlingStrategy":"validation","validationCode":"const cleaned = String($json.text ?? '').replace(/```json|```/g, '').trim();\nconst parsed = JSON.parse(cleaned);\nconst arr = Array.isArray(parsed) ? parsed : Object.values(parsed).find(Array.isArray);\nif (!arr) throw new Error('The JSON is not an array.');","typeGuard":"function unwrapLlmArray(parsed) {\n  if (Array.isArray(parsed)) return parsed;\n  if (parsed && typeof parsed === 'object') {\n    const arrays = Object.values(parsed).filter(Array.isArray);\n    if (arrays.length === 1) return arrays[0];\n  }\n  return null;\n}","tryCatchPattern":null,"preventionTips":["Keep the LLM prompt in both cloned workflows in sync when you strengthen the array-only instruction.","Unwrap common envelopes (results/data/items keys) before the Array.isArray check.","Fail visibly (Stop and Error or a dedicated error branch) instead of silently passing {error} downstream."],"tags":["n8n","llm","openrouter","json-parsing","ai-output"],"backgroundTag":null,"analyzedSha":"94007c1445d9258a7da116646b79473e7c7c3282","analyzedAt":"2026-08-15T04:10:37.591Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}