Zie619/n8n-workflows · error · Error

Invalid data structure

Error message

Invalid data structure

What it means

Identical logic to error 44 but in workflow 1850 (a copy of the Umami analytics workflow). The 'Parse Umami data' node dereferences data.pageviews.value etc. inside a try block; a missing sub-object throws a TypeError that the catch converts to 'Invalid data structure'. The message unfortunately hides the original error.

Source

Thrown at workflows/Code/1850_Code_Schedule_Automation_Webhook.json:192

      "parameters": {
        "color": 4,
        "width": 393.16558441558414,
        "height": 504.17207792207796,
        "content": "## Save analysis to baserow\n\nYou need to create a table in advance to save. \n- Date (date)\n- Summary (Long text)\n- Top pages (Long text)\n- Blog name (Long text)"
      },
      "typeVersion": 1,
      "notes": "This stickyNote node performs automated tasks as part of the workflow."
    },
    {
      "id": "f64cdfbd-712f-461c-b025-25f37e2bded8",
      "name": "Parse Umami data",
      "type": "n8n-nodes-base.code",
      "position": [
        940,
        260
      ],
      "parameters": {
        "jsCode": "function transformToUrlString(items) {\n    // In n8n, we need to check if items is an array and get the json property\n    const data = items[0].json;\n    \n    if (!data) {\n        console.log('No valid data found');\n        return encodeURIComponent(JSON.stringify([]));\n    }\n    \n    try {\n        // Create a simplified object with the metrics\n        const simplified = {\n            pageviews: {\n                value: parseInt(data.pageviews.value) || 0,\n                prev: parseInt(data.pageviews.prev) || 0\n            },\n            visitors: {\n                value: parseInt(data.visitors.value) || 0,\n                prev: parseInt(data.visitors.prev) || 0\n            },\n            visits: {\n                value: parseInt(data.visits.value) || 0,\n                prev: parseInt(data.visits.prev) || 0\n            },\n            bounces: {\n                value: parseInt(data.bounces.value) || 0,\n                prev: parseInt(data.bounces.prev) || 0\n            },\n            totaltime: {\n                value: parseInt(data.totaltime.value) || 0,\n                prev: parseInt(data.totaltime.prev) || 0\n            }\n        };\n        \n        return encodeURIComponent(JSON.stringify(simplified));\n    } catch (error) {\n        console.log('Error processing data:', error);\n        throw new Error('Invalid data structure');\n    }\n}\n\n// Get the input data\nconst items = $input.all();\n\n// Process the data\nconst result = transformToUrlString(items);\n\n// Return the result\nreturn { json: { urlString: result } };"
      },
      "typeVersion": 2,
      "notes": "This code node performs automated tasks as part of the workflow."
    },
    {
      "id": "470715b6-0878-48b8-b6c6-40de27fbc966",
      "name": "Send data to A.I.",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        1140,
        260
      ],
      "parameters": {
        "url": "{{ $env.API_BASE_URL }}",
        "method": "POST",
        "options": {},
        "jsonBody": "={\n  \"model\": \"meta-llama/llama-3.1-70b-instruct:free\",\n  \"messages\": [\n    {\n      \"role\": \"user\",\n      \"content\": \"You are an SEO expert. Here is data from Umami analytics of Pennibnotes.com. Where X is URL and Y is number of visitors. Give me a table summary of this data in markdown format:{{ $('Parse Umami data').item.json.urlString }}.\"\n    }\n  ]\n}",
        "sendBody": true,

View on GitHub (pinned to 94007c1445)

Solutions

  1. Open the execution log and read the 'Error processing data:' line to see the real TypeError and which field is missing.
  2. Validate the upstream Umami response (status 200, contains the five metric keys) before parsing.
  3. Rewrite the reads with optional chaining so absent metrics default to 0 instead of throwing.
  4. Keep this workflow copy in sync with fixes made to its sibling (1671) — they share the bug.

Example fix

// before
const simplified = {
  pageviews: { value: parseInt(data.pageviews.value) || 0, prev: parseInt(data.pageviews.prev) || 0 },
  // ...
};

// after
const metric = (k) => ({ value: parseInt(data?.[k]?.value) || 0, prev: parseInt(data?.[k]?.prev) || 0 });
const simplified = ['pageviews','visitors','visits','bounces','totaltime'].reduce((acc, k) => (acc[k] = metric(k), acc), {});
Defensive patterns

Strategy: type-guard

Validate before calling

const data = items[0]?.json;
const ok = data && ['pageviews','visitors','visits','bounces','totaltime'].every(k => data[k] && 'value' in data[k]);

Type guard

function isUmamiStats(d) {
  return Boolean(d && ['pageviews','visitors','visits','bounces','totaltime'].every(k => d?.[k]?.value !== undefined));
}

Try / catch

catch (error) { throw new Error(`Invalid Umami data structure: ${error.message}`); } // preserve the cause

Prevention

When it happens

Trigger: The Umami stats endpoint response lacks any of pageviews/visitors/visits/bounces/totaltime (auth error body, version-drift payload, empty date range), making one of the chained .value reads throw.

Common situations: Umami token expired so the HTTP node emitted an error JSON; Umami upgraded with a changed stats schema; website id misconfigured; scheduled run hitting a range with no data.

Related errors


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