{"record":{"id":"ec117fb76e7bd5c1","repo":"n8n-io/n8n","slug":"failed-to-parse-xlsx-attachment-filename-m","errorCode":null,"errorMessage":"Failed to parse xlsx \"${attachment.fileName}\": ${message}","messagePattern":"Failed to parse xlsx \"(.+?)\": (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"packages/@n8n/instance-ai/src/parsers/xlsx-parser.ts","lineNumber":36,"sourceCode":"export async function extractXlsxAsRows(\n\tattachment: AttachmentInfo,\n\tattachmentIndex: number,\n\tinput: ParseFileInput,\n): Promise<ParseFileOutput> {\n\tconst decoded = Buffer.from(attachment.data, 'base64');\n\tif (decoded.length > MAX_DECODED_SIZE_BYTES) {\n\t\tthrow new Error(formatSizeLimitMessage(decoded.length));\n\t}\n\tassertOoxmlWithinBounds(decoded, attachment.fileName);\n\n\tconst XLSX = await import('@e965/xlsx');\n\n\tlet workbook: ReturnType<typeof XLSX.read>;\n\ttry {\n\t\tworkbook = XLSX.read(decoded, { type: 'buffer' });\n\t} catch (error) {\n\t\tconst message = error instanceof Error ? error.message : 'unknown error';\n\t\tthrow new Error(`Failed to parse xlsx \"${attachment.fileName}\": ${message}`);\n\t}\n\n\tconst firstSheetName = workbook.SheetNames[0];\n\tif (!firstSheetName) {\n\t\tthrow new Error(`xlsx \"${attachment.fileName}\" has no sheets.`);\n\t}\n\n\tconst sheet = workbook.Sheets[firstSheetName];\n\tconst json = XLSX.utils.sheet_to_json<Record<string, unknown>>(sheet, {\n\t\tblankrows: false,\n\t\tdefval: null,\n\t});\n\n\tif (json.length === 0) {\n\t\tthrow new Error(`xlsx \"${attachment.fileName}\" sheet \"${firstSheetName}\" is empty.`);\n\t}\n\n\t// Round-trip through the JSON path of parseStructuredFile so types","sourceCodeStart":18,"sourceCodeEnd":54,"githubUrl":"https://github.com/n8n-io/n8n/blob/5ac6606e81f67bb9534255570cd4e86fd8101eee/packages/@n8n/instance-ai/src/parsers/xlsx-parser.ts#L18-L54","documentation":"Thrown by extractXlsxAsRows (xlsx-parser.ts:34-37) when SheetJS XLSX.read throws while parsing the decoded buffer. The original error message is interpolated into the thrown Error so the underlying cause (corrupt zip, unsupported format, encryption) is visible. This is a parser-level failure distinct from the structural checks that follow.","triggerScenarios":"A file labeled .xlsx that is not a valid OOXML zip: a legacy .xls saved with the wrong extension, a password-protected workbook, a truncated download, or a corrupted archive. Also triggered if SheetJS encounters an unsupported feature it cannot decode.","commonSituations":"User renames .xls to .xlsx; file was downloaded incompletely; workbook is encrypted; a third-party tool produced a non-conformant OOXML zip; version skew between SheetJS (@e965/xlsx) and the producing application.","solutions":["Re-save the workbook as a standard .xlsx from Excel/Google Sheets/LibreOffice.","Remove password protection before attaching.","Verify the file is a valid ZIP (e.g. check the PK header) before attaching.","If the source is legacy .xls, convert to .xlsx or to CSV first."],"exampleFix":"// before: attach legacy 'data.xls' renamed to 'data.xlsx'\n// after:  open in Excel, 'Save As -> .xlsx', then attach","handlingStrategy":"try-catch","validationCode":"// Cheap structural check before calling extractXlsxAsRows\nconst decoded = Buffer.from(attachment.data, 'base64');\nconst isZip = decoded.length >= 4 && decoded[0] === 0x50 && decoded[1] === 0x4b;\nif (!isZip) throw new Error('Not a valid xlsx (ZIP) container');","typeGuard":"function looksLikeXlsxZip(buf: Buffer): boolean {\n  return buf.length >= 4 && buf[0] === 0x50 && buf[1] === 0x4b && (buf[2] === 0x03 || buf[2] === 0x05 || buf[2] === 0x07);\n}","tryCatchPattern":"try { return await extractXlsxAsRows(attachment, idx, input); }\ncatch (e) {\n  if (e instanceof Error && e.message.startsWith('Failed to parse xlsx')) {\n    // prompt user to re-save as standard .xlsx; do not retry the same bytes\n  }\n  throw e;\n}","preventionTips":["Re-save .xlsx from a conformant application before attaching.","Remove password protection from workbooks.","Reject legacy .xls by mime type (application/vnd.ms-excel) up front."],"tags":["xlsx","sheetjs","corrupt-file","attachment-parsing"],"backgroundTag":null,"analyzedSha":"5ac6606e81f67bb9534255570cd4e86fd8101eee","analyzedAt":"2026-08-12T05:26:35.080Z","schemaVersion":2},"datasetVersion":"2026-08-12T18:17:37.767Z"}