n8n-io/n8n · error
Attachment exceeds maximum size of 10.0 MB (got ${formatMB(a
Error message
Attachment exceeds maximum size of 10.0 MB (got ${formatMB(actualBytes)}) What it means
Thrown by extractXlsxAsRows (xlsx-parser.ts:24-25) when the decoded .xlsx byte length exceeds MAX_DECODED_SIZE_BYTES (10MB). This is the xlsx-specific twin of error 503; the decoded (not base64) size is measured before SheetJS ever opens the workbook. A subsequent assertOoxmlWithinBounds check guards uncompressed (decompression-bomb) size separately.
Source
Thrown at packages/@n8n/instance-ai/src/parsers/xlsx-parser.ts:25
type ParseFileInput,
type ParseFileOutput,
} from './structured-file-parser';
/**
* Extracts the first sheet of an `.xlsx` workbook as tabular rows.
*
* Strategy: convert the sheet to CSV text via SheetJS, then route through the
* existing `parseStructuredFile` so column normalization, type inference, and
* truncation budgets stay in one place.
*/
export async function extractXlsxAsRows(
attachment: AttachmentInfo,
attachmentIndex: number,
input: ParseFileInput,
): Promise<ParseFileOutput> {
const decoded = Buffer.from(attachment.data, 'base64');
if (decoded.length > MAX_DECODED_SIZE_BYTES) {
throw new Error(formatSizeLimitMessage(decoded.length));
}
assertOoxmlWithinBounds(decoded, attachment.fileName);
const XLSX = await import('@e965/xlsx');
let workbook: ReturnType<typeof XLSX.read>;
try {
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.`);
}
View on GitHub (pinned to 5ac6606e81)
Solutions
- Strip embedded media, unused sheets, and styling from the workbook.
- Keep only the sheet the task needs and save as a lean .xlsx.
- Convert the relevant sheet to CSV and attach as text/csv if a spreadsheet is not required.
- Sample/filter rows before exporting.
Example fix
// before: attach a 13MB .xlsx with embedded charts // after: export the target sheet as CSV (~1MB) and attach as text/csv
Defensive patterns
Strategy: validation
Validate before calling
import { MAX_DECODED_SIZE_BYTES } from './structured-file-parser';
const decoded = Buffer.from(attachment.data, 'base64');
if (decoded.length > MAX_DECODED_SIZE_BYTES) {
throw new Error(`xlsx too large after decode: ${decoded.length} bytes`);
} Type guard
function xlsxWithinDecodedLimit(base64: string, limit = MAX_DECODED_SIZE_BYTES): boolean {
return Buffer.byteLength(base64, 'base64') <= limit;
} Try / catch
try { return await extractXlsxAsRows(attachment, idx, input); }
catch (e) {
if (e instanceof Error && e.message.startsWith('Attachment exceeds')) {
// strip embedded media / unused sheets, re-save, retry
}
throw e;
} Prevention
- Remove embedded images, charts, and unused sheets before exporting.
- Convert to CSV when a spreadsheet is not strictly needed.
- Measure decoded (not base64) size before attaching.
When it happens
Trigger: An .xlsx attachment whose decoded bytes > 10MB. Because .xlsx is a ZIP, the base64 string can be considerably smaller than the decoded buffer.
Common situations: A workbook with embedded images, many sheets, or large cached formula values; a file that is mostly formatting overhead; user assumes the base64 length is the enforced limit.
Related errors
- Attachment exceeds maximum size of 10.0 MB (got ${formatMB(a
- Too many columns: ${rawHeaders.length} (max ${MAX_COLUMNS})
- Failed to parse xlsx "${attachment.fileName}": ${message}
- xlsx "${attachment.fileName}" has no sheets.
- xlsx "${attachment.fileName}" sheet "${firstSheetName}" is e
AI-assisted analysis of n8n-io/n8n@5ac6606e81 (2026-08-12).
Data as JSON: /api/errors/22908b125c7ee295.
Report an issue: GitHub.