n8n-io/n8n · error
xlsx "${attachment.fileName}" sheet "${firstSheetName}" is e
Error message
xlsx "${attachment.fileName}" sheet "${firstSheetName}" is empty. What it means
Thrown by extractXlsxAsRows (xlsx-parser.ts:50-52) when XLSX.utils.sheet_to_json returns an empty array for the first sheet. The sheet exists but contains no rows (blankrows: false collapses empty rows, so an all-blank sheet also triggers this). Distinct from error 510: the sheet is present, just has no data.
Source
Thrown at packages/@n8n/instance-ai/src/parsers/xlsx-parser.ts:51
workbook = XLSX.read(decoded, { type: 'buffer' });
} catch (error) {
const message = error instanceof Error ? error.message : 'unknown error';
throw new Error(`Failed to parse xlsx "${attachment.fileName}": ${message}`);
}
const firstSheetName = workbook.SheetNames[0];
if (!firstSheetName) {
throw new Error(`xlsx "${attachment.fileName}" has no sheets.`);
}
const sheet = workbook.Sheets[firstSheetName];
const json = XLSX.utils.sheet_to_json<Record<string, unknown>>(sheet, {
blankrows: false,
defval: null,
});
if (json.length === 0) {
throw new Error(`xlsx "${attachment.fileName}" sheet "${firstSheetName}" is empty.`);
}
// Round-trip through the JSON path of parseStructuredFile so types
// (numbers, booleans) survive and we share row/column budget logic.
const jsonAttachment: AttachmentInfo = {
data: Buffer.from(JSON.stringify(json), 'utf-8').toString('base64'),
mimeType: 'application/json',
fileName: attachment.fileName,
};
const result = parseStructuredFile(jsonAttachment, attachmentIndex, {
...input,
format: 'json',
});
// Preserve original mime type and report xlsx as the format on output.
return { ...result, mimeType: attachment.mimeType, format: 'xlsx' };
}View on GitHub (pinned to 5ac6606e81)
Solutions
- Move the data onto the first sheet, or delete empty preceding sheets so the data sheet becomes first.
- Confirm the sheet has actual cell values, not just formatting.
- If the data is on another sheet, reorder sheets so the populated one is first.
- Attach the data directly as CSV/JSON instead.
Example fix
// before: first sheet is blank, data is on sheet 2 // after: move data sheet to the first position, save, attach
Defensive patterns
Strategy: try-catch
Validate before calling
// Pre-check the first sheet has rows
// const json = XLSX.utils.sheet_to_json(wb.Sheets[wb.SheetNames[0]], { blankrows: false, defval: null });
// if (!json.length) throw new Error('first sheet is empty'); Type guard
function firstSheetHasRows(json: unknown[]): boolean {
return Array.isArray(json) && json.length > 0;
} Try / catch
try { return await extractXlsxAsRows(attachment, idx, input); }
catch (e) {
if (e instanceof Error && /sheet .* is empty\.$/.test(e.message)) {
// request data on the first sheet or reorder sheets
}
throw e;
} Prevention
- Put the data sheet first before exporting.
- Clear formatting-only sheets so the populated one is first.
- If only formatting exists, attach CSV/JSON instead.
When it happens
Trigger: The first sheet is entirely empty or contains only blank cells; the sheet has a header row but sheet_to_json with defval:null still yields no records because blankrows:false removed everything; only formatting/chart objects exist with no cell data.
Common situations: User exports a chart-only sheet; a sheet whose data was cleared but formatting kept; the real data lives on a non-first sheet (only SheetNames[0] is read).
Related errors
- xlsx "${attachment.fileName}" has no sheets.
- Nested ${Array.isArray(value) ? 'array' : 'object'} found at
- Unsupported format for "${attachment.fileName}" (${attachmen
- Unsupported attachment type: ${summary}
- Attachment exceeds maximum size of 10.0 MB (got ${formatMB(a
AI-assisted analysis of n8n-io/n8n@5ac6606e81 (2026-08-12).
Data as JSON: /api/errors/d515627eeb6047ae.
Report an issue: GitHub.