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

  1. Move the data onto the first sheet, or delete empty preceding sheets so the data sheet becomes first.
  2. Confirm the sheet has actual cell values, not just formatting.
  3. If the data is on another sheet, reorder sheets so the populated one is first.
  4. 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

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


AI-assisted analysis of n8n-io/n8n@5ac6606e81 (2026-08-12). Data as JSON: /api/errors/d515627eeb6047ae. Report an issue: GitHub.