iOfficeAI/OfficeCLI · error · ArgumentException

Import exceeds Excel's row limit: data would reach row {endR

Error message

Import exceeds Excel's row limit: data would reach row {endRowReq} (maximum {ExcelMaxRow}). Reduce the CSV or change the start cell.

What it means

Thrown by ExcelHandler.Import as a DOS-hardening guard BEFORE writing any cells, when startRow + rows.Count - 1 would exceed Excel's maximum of 1,048,576 rows. Without this check an oversized import spun indefinitely instead of erroring.

Source

Thrown at src/officecli/Handlers/Excel/ExcelHandler.Import.cs:54

        var startColIdx = ColumnNameToIndex(startCol);

        // Parse CSV
        var rows = ParseCsv(csvContent, delimiter);
        if (rows.Count == 0)
            return "No data to import";

        int maxCols = 0;
        for (int r = 0; r < rows.Count; r++)
            if (rows[r].Count > maxCols) maxCols = rows[r].Count;

        // DOS-hardening: reject imports that exceed Excel's sheet dimensions
        // BEFORE writing anything. Without this an over-sized CSV (e.g. >XFD
        // columns or >1048576 rows) spun indefinitely instead of erroring.
        const int ExcelMaxRow = 1048576;
        const int ExcelMaxCol = 16384; // XFD (ColumnNameToIndex is 1-based)
        long endRowReq = (long)startRow + rows.Count - 1;
        if (endRowReq > ExcelMaxRow)
            throw new ArgumentException(
                $"Import exceeds Excel's row limit: data would reach row {endRowReq} " +
                $"(maximum {ExcelMaxRow}). Reduce the CSV or change the start cell.");
        long endColIdx = (long)startColIdx + maxCols - 1;
        if (endColIdx > ExcelMaxCol)
            throw new ArgumentException(
                $"Import exceeds Excel's column limit: data would reach column {endColIdx} " +
                $"(maximum {ExcelMaxCol} / XFD). Reduce the CSV width or change the start cell.");

        // BUG-R11-import-dup-row BUG-11: import previously always appended a
        // brand-new <row r="N">, producing duplicate row entries when the
        // target rows already existed (Excel auto-repaired by keeping the
        // first one, silently losing imported data). Upsert by RowIndex —
        // reuse an existing row, otherwise insert a new one in sorted position.
        //
        // PERF(dos-hardening): the previous implementation re-scanned the whole
        // SheetData (LINQ FirstOrDefault) for every imported row AND every cell,
        // making a bulk import O(rows*cells * existing) — a 100k-row CSV took
        // 9+ minutes. Pre-index existing rows once and walk them with an

View on GitHub (pinned to 1ced45e900)

Solutions

  1. Reduce the CSV to at most (1048576 - startRow + 1) rows before importing.
  2. Move the startCell earlier (A1) to maximize available rows.
  3. Split the data across multiple sheets or filter/aggregate the source before import.

Example fix

// before
var csv = File.ReadAllText("huge.csv");           // 1.1M rows
excel.Import("/Sheet1", csv, ',', false, "A1");

// after (trim to the sheet capacity)
var rows = File.ReadAllLines("huge.csv").Take(1_048_576);
var csv  = string.Join('\n', rows);
excel.Import("/Sheet1", csv, ',', false, "A1");
Defensive patterns

Strategy: validation

Validate before calling

const int ExcelMaxRow = 1048576;
var (startCol, startRow) = ExcelHandler.ParseCellReference(startCell.ToUpperInvariant());
long endRow = (long)startRow + rowCount - 1;
if (endRow > ExcelMaxRow)
    throw new ArgumentException($"Import would reach row {endRow} (max {ExcelMaxRow}).");

Prevention

When it happens

Trigger: Importing a CSV with more rows than Excel can hold from the given startRow, e.g. startCell=A1 with a 1,100,000-row CSV, or startCell=A100000 with a 1,000,000-row CSV (the offset pushes the end past the limit).

Common situations: Bulk-ingesting a database extract or log without checking row count; mis-estimating CSV size; choosing a startCell deep in the sheet (e.g. A500000) and then importing a large payload.

Related errors


AI-assisted analysis of iOfficeAI/OfficeCLI@1ced45e900 (2026-08-13). Data as JSON: /api/errors/14105c25310211e0. Report an issue: GitHub.