Zie619/n8n-workflows · error · Error
Invalid input data format
Error message
Invalid input data format
What it means
Thrown by the 'Parse Data' Code node when $json.data is absent, i.e. the item coming from the previous HTTP request node does not carry the expected data field containing a JSON string. The node JSON.parses $json.data and splits parsedData.reply.available / .unavailable into Domain/Availability rows for Excel export. Any upstream response that changes shape (error body, envelope change, empty reply) breaks the guard.
Source
Thrown at workflows/Wait/1954_Wait_Code_Automation_Webhook.json:153
"parameters": {
"url": "{{ $env.BASE_URL }}",
"options": {}
},
"retryOnFail": true,
"typeVersion": 4.2,
"waitBetweenTries": 5000,
"notes": "This httpRequest node performs automated tasks as part of the workflow."
},
{
"id": "c4f38893-636a-4293-9e10-395be30683d0",
"name": "Parse Data",
"type": "n8n-nodes-base.code",
"position": [
500,
-200
],
"parameters": {
"jsCode": "// Ensure input data exists\nif (!$json || !$json.data) {\n throw new Error(\"Invalid input data format\");\n}\n\n// Parse the JSON string inside `data`\nlet parsedData;\ntry {\n parsedData = JSON.parse($json.data);\n} catch (error) {\n throw new Error(\"Error parsing JSON data: \" + error.message);\n}\n\n// Extract available and unavailable domains safely\nconst availableDomains = parsedData.reply?.available ? Object.values(parsedData.reply.available) : [];\nconst unavailableDomains = parsedData.reply?.unavailable ? Object.values(parsedData.reply.unavailable) : [];\n\n// Prepare the output array\nconst output = [];\n\n// Process available domains\navailableDomains.forEach(domainObj => {\n if (domainObj && domainObj.domain) {\n output.push({\n Domain: domainObj.domain,\n Availability: \"Available\"\n });\n }\n});\n\n// Process unavailable domains\nunavailableDomains.forEach(domain => {\n if (typeof domain === \"string\") {\n output.push({\n Domain: domain,\n Availability: \"Unavailable\"\n });\n } else if (typeof domain === \"object\" && domain.domain) {\n output.push({\n Domain: domain.domain,\n Availability: \"Unavailable\"\n });\n }\n});\n\n// Return the structured data\nreturn output;"
},
"typeVersion": 2,
"notes": "This code node performs automated tasks as part of the workflow."
},
{
"id": "ec7b8311-65b7-45b0-85ae-b91d7c82e123",
"name": "Convert to Excel",
"type": "n8n-nodes-base.convertToFile",
"position": [
500,
0
],
"parameters": {
"options": {
"fileName": "domain_results.xlsx"
},
"operation": "xlsx",
"binaryPropertyName": "={{ $json.MergedDomains }}"View on GitHub (pinned to 94007c1445)
Solutions
- Execute the HTTP node standalone and inspect its output keys to see what the API actually returned (often an error message explains it).
- If $json.data can be an object, handle both: typeof d === 'string' ? JSON.parse(d) : d.
- Add an IF node on the HTTP response status/code so error payloads route to an error branch before parsing.
- Fix auth/rate-limit on the upstream API if error envelopes are the cause.
Example fix
// before
if (!$json || !$json.data) {
throw new Error("Invalid input data format");
}
let parsedData;
try {
parsedData = JSON.parse($json.data);
} catch (error) {
throw new Error("Error parsing JSON data: " + error.message);
}
// after - accept object or string, report the real shape
if (!$json || (!$json.data && !$json.reply)) {
throw new Error(`Invalid input data format. Item keys: ${$json ? Object.keys($json).join(', ') : 'null'}`);
}
const raw = $json.data ?? $json;
const parsedData = typeof raw === 'string' ? JSON.parse(raw) : raw; Defensive patterns
Strategy: try-catch
Validate before calling
if (!$json || (!$json.data && !$json.reply)) {
throw new Error(`Invalid input data format. Keys: ${$json ? Object.keys($json).join(', ') : 'null'}`);
}
const raw = $json.data ?? $json;
const parsed = typeof raw === 'string' ? JSON.parse(raw) : raw;
if (!parsed?.reply) {
throw new Error(`Unexpected API envelope: ${JSON.stringify(parsed).slice(0, 200)}`);
} Type guard
const hasDomainReply = (p) => p != null && p.reply != null && (p.reply.available != null || p.reply.unavailable != null);
Try / catch
try {
const parsed = typeof $json.data === 'string' ? JSON.parse($json.data) : $json.data;
if (!parsed?.reply) throw new Error('API envelope missing .reply');
return toRows(parsed);
} catch (e) {
throw new Error(`Parse Data failed: ${e.message}; body preview: ${JSON.stringify($json).slice(0, 200)}`);
} Prevention
- Check the HTTP node's response format option (String vs JSON) — it determines whether $json.data is a string to parse or already an object.
- Route non-2xx responses to an error branch (IF on status) before parsing nodes.
- Snapshot a real API response as pinned data to lock the envelope shape.
When it happens
Trigger: The domain-availability API returned an error envelope (e.g., {error: 'rate limited'}) with no .data, the response was already parsed to an object so $json.data is an object (guard passes but JSON.parse throws the sibling error), a proxy/queue step renamed the field, or the HTTP node returned the raw body under a different property.
Common situations: API outage or auth expiry returning HTML/JSON error instead of the normal payload, response-format option on the HTTP Request node changed (String vs JSON), or upstream API version bump re-wrapping the reply.
Related errors
- Approved quantity must be greater than 0
- The video ID parameter is empty.
- One or more input arrays are empty. Check your previous node
- Invalid data structure
- PII column names are missing in the input data.
AI-assisted analysis of Zie619/n8n-workflows@94007c1445 (2026-08-15).
Data as JSON: /api/errors/970d104488e37d61.
Report an issue: GitHub.