iOfficeAI/OfficeCLI · error · ArgumentException
table ref '{rangeRef}' has 1 row; tables must have at least
Error message
table ref '{rangeRef}' has 1 row; tables must have at least 2 rows (header + 1 data row). Pass headerRow=false for a data-only single-row table. What it means
Thrown by AddTable's i103 guard when headerRow is true (the default) and the table ref covers exactly one row. A header-only ref (e.g. A1:C1) produces an <autoFilter> that Excel rejects with 'Removed Feature: AutoFilter', which cascades and drops the whole table on open. The handler requires at least a header plus one data row unless headerRow=false is set for a data-only single-row table.
Source
Thrown at src/officecli/Handlers/Excel/ExcelHandler.Add.Tables.cs:1216
if (!anyNonEmpty) break;
endRow = probeRow;
probeRow++;
}
rangeRef = $"{startCol}{startRow}:{endCol}{endRow}";
}
}
// i103: when headerRow=true (the default) the table ref must cover
// at least 2 rows — header plus one data row. A header-only ref
// (e.g. A1:C1) produces an <autoFilter> that Excel rejects with
// "Removed Feature: AutoFilter from /xl/tables/tableN.xml part",
// which cascades to drop the whole table on file open. Reject up
// front with a clear message instead of letting Excel silently
// strip the table. headerRow=false is allowed to be a single
// (data-only) row.
if (hasHeader && startRow == endRow)
{
throw new ArgumentException(
$"table ref '{rangeRef}' has 1 row; tables must have at least 2 rows " +
"(header + 1 data row). Pass headerRow=false for a data-only single-row table.");
}
// CONSISTENCY(table-totalrow): a:totalsRowShown MUST point at a row
// OUTSIDE the data area. Previously we reused endRow as the totals
// row, which overwrote whatever data lived on that last row. Expand
// the ref by one row so the totals row is appended below the data
// instead of stamping over it.
if (hasTotalRow)
{
endRow += 1;
rangeRef = $"{startCol}{startRow}:{endCol}{endRow}";
}
string[] colNames;
if (properties.TryGetValue("columns", out var tblColsStr))
{View on GitHub (pinned to 1ced45e900)
Solutions
- Extend the ref to at least two rows (header + data), e.g. ref=A1:C2.
- If a single data-only row is intended, pass headerRow=false.
- Verify startRow equals endRow is the actual condition; any 2+ row ref passes.
Example fix
// before add /Sheet1/table --prop ref=A1:C1 // after (header + data) add /Sheet1/table --prop ref=A1:C2 // or data-only add /Sheet1/table --prop ref=A1:C1 --prop headerRow=false
Defensive patterns
Strategy: validation
Validate before calling
// Validate a table ref has >=2 rows when headerRow is true (default).
static bool TryValidateHeaderRef(string rangeRef, bool headerRow, out string error)
{
error = null;
if (!headerRow) return true;
var (startRow, endRow) = ParseRows(rangeRef); // pseudo: extract numeric rows
if (startRow == endRow)
{
error = $"table ref '{rangeRef}' has 1 row; pass headerRow=false for data-only.";
return false;
}
return true;
} Try / catch
try { handler.Add(parentPath, "table", null, props); }
catch (ArgumentException ex) when (ex.Message.Contains("tables must have at least 2 rows"))
{ /* extend ref to 2+ rows or set headerRow=false, then retry */ } Prevention
- When templating from a header row, extend the ref to include at least one data row.
- Set headerRow=false explicitly for data-only single-row tables.
- Validate startRow != endRow in any builder that defaults headerRow=true.
When it happens
Trigger: Calling Add('/Sheet1/table', ...) with ref=A1:C1 (one row) and no headerRow=false, i.e. relying on the default headerRow=true.
Common situations: Building a table from a header-only template, auto-sizing the ref to the used header row, or intending a single-row data table.
Related errors
- Table ref overlaps existing table '{existing.Name?.Value ??
- Invalid array constant: '{badElem}'. Inline arrays {...} may
- Defined name '{nrName}' collides with the table name '{exist
- Property 'sqref' (or 'range'/'ref') is required for validati
- Sheet not found: {tblSheetName}
AI-assisted analysis of iOfficeAI/OfficeCLI@1ced45e900 (2026-08-13).
Data as JSON: /api/errors/6d89dfb4b2c6f0db.
Report an issue: GitHub.