{"record":{"id":"48752c8862ba436a","repo":"n8n-io/n8n","slug":"nested-array-isarray-value-array-object","errorCode":null,"errorMessage":"Nested ${Array.isArray(value) ? 'array' : 'object'} found at key \"${key}\". Only flat objects are supported.","messagePattern":"Nested (.+?) found at key \"(.+?)\"\\. Only flat objects are supported\\.","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"packages/@n8n/instance-ai/src/parsers/structured-file-parser.ts","lineNumber":354,"sourceCode":"\t\t\tthrow new Error('JSON array items must be flat objects (not arrays, nulls, or primitives)');\n\t\t}\n\t\tconst dangerousKey = hasDangerousKey(item as Record<string, unknown>);\n\t\tif (dangerousKey) {\n\t\t\tthrow new Error(`Dangerous key \"${dangerousKey}\" found in JSON data`);\n\t\t}\n\t\tfor (const key of Object.keys(item as Record<string, unknown>)) {\n\t\t\tkeySet.add(key);\n\t\t}\n\t}\n\n\tconst rawHeaders = [...keySet];\n\n\t// Validate all values are flat\n\tfor (const item of parsed) {\n\t\tconst obj = item as Record<string, unknown>;\n\t\tfor (const [key, value] of Object.entries(obj)) {\n\t\t\tif (value !== null && typeof value === 'object') {\n\t\t\t\tthrow new Error(\n\t\t\t\t\t`Nested ${Array.isArray(value) ? 'array' : 'object'} found at key \"${key}\". Only flat objects are supported.`,\n\t\t\t\t);\n\t\t\t}\n\t\t}\n\t}\n\n\treturn { rawHeaders, allRows: parsed as Array<Record<string, unknown>> };\n}\n\n// ── Main parse function ─────────────────────────────────────────────────────\n\nexport function parseStructuredFile(\n\tattachment: AttachmentInfo,\n\tattachmentIndex: number,\n\tinput: ParseFileInput,\n): ParseFileOutput {\n\t// Decode base64\n\tlet decoded: Buffer;","sourceCodeStart":336,"sourceCodeEnd":372,"githubUrl":"https://github.com/n8n-io/n8n/blob/5ac6606e81f67bb9534255570cd4e86fd8101eee/packages/@n8n/instance-ai/src/parsers/structured-file-parser.ts#L336-L372","documentation":"Thrown by parseJson() during the second validation pass (structured-file-parser.ts:353) when any value in a JSON object is itself a non-null object or array. parseStructuredFile only emits flat tabular rows, so nested structures are rejected before column type inference runs. The check is value-based and runs after header collection.","triggerScenarios":"A JSON array attachment where any object has a value that is an object literal ({...}) or array ([...]), e.g. {\"id\": 1, \"tags\": [\"a\",\"b\"]} or {\"user\": {\"name\":\"x\"}}. Also reached via the xlsx JSON round-trip when a sheet cell is serialized as a nested structure.","commonSituations":"Sending a denormalized REST response (objects with nested related resources) to a tool expecting tabular rows; LLM-generated eval-data with array fields; a sheet whose merged/formula cells serialize to objects via SheetJS.","solutions":["Flatten nested fields before attaching: convert {\"user\":{\"name\":\"x\"}} to {\"user.name\":\"x\"}, and arrays to comma-joined strings or separate rows.","If the data is genuinely hierarchical, do not use parseStructuredFile — preprocess into a tabular projection first.","Validate with a recursive walk that rejects non-primitive values before calling parseStructuredFile."],"exampleFix":"// before: [{ \"id\": 1, \"tags\": [\"a\",\"b\"] }]\n// after:  [{ \"id\": 1, \"tags\": \"a,b\" }]","handlingStrategy":"validation","validationCode":"function isFlatRecord(v: unknown): v is Record<string, string | number | boolean | null> {\n  if (typeof v !== 'object' || v === null || Array.isArray(v)) return false;\n  for (const val of Object.values(v)) {\n    if (val !== null && typeof val === 'object') return false;\n  }\n  return true;\n}\nif (!Array.isArray(parsed) || !parsed.every(isFlatRecord)) {\n  throw new Error('Flatten nested fields before attaching');\n}","typeGuard":"function isFlatValue(v: unknown): v is string | number | boolean | null {\n  return v === null || typeof v === 'string' || typeof v === 'number' || typeof v === 'boolean';\n}","tryCatchPattern":"try { return parseStructuredFile(attachment, idx, input); }\ncatch (e) {\n  if (e instanceof Error && e.message.startsWith('Nested ')) {\n    // prompt caller to flatten nested fields\n  }\n  throw e;\n}","preventionTips":["Flatten objects to dot-notation keys and arrays to joined strings before upload.","Project REST responses to a tabular shape at the source.","Validate nested structure with a recursive walker before attaching."],"tags":["json","attachment-parsing","data-shape","validation"],"backgroundTag":null,"analyzedSha":"5ac6606e81f67bb9534255570cd4e86fd8101eee","analyzedAt":"2026-08-12T05:26:35.080Z","schemaVersion":2},"datasetVersion":"2026-08-12T13:17:24.610Z"}