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

  1. Strengthen the LLM prompt: 'Respond with ONLY a raw JSON array, no wrapper object, no prose, no code fences.'
  2. Unwrap common envelope shapes before the array check (see exampleFix).
  3. Check the {error} output item downstream before using chunk — the SerpAPI node currently consumes it blindly as its q parameter.
  4. 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

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


AI-assisted analysis of Zie619/n8n-workflows@94007c1445 (2026-08-15). Data as JSON: /api/errors/9c5090c11f4a7ebd. Report an issue: GitHub.