iOfficeAI/OfficeCLI · error · System.ArgumentException
Invalid 'outline' value: '{addColOutline}'. Expected an inte
Error message
Invalid 'outline' value: '{addColOutline}'. Expected an integer 0-7 (outline/group level). What it means
Thrown by AddCol when the column's outline/group level property fails to parse as a byte in the range 0-7. The property is read from any of the keys outline, outlinelevel, or group. The OOXML schema restricts the column outline level to 0-7, so any value outside that would write schema-invalid OOXML that Excel rejects (0x800A03EC). The guard rejects the bad input before it corrupts the file.
Source
Thrown at src/officecli/Handlers/Excel/ExcelHandler.Add.Cells.cs:1133
// shift, never gated on stored column width (standard spreadsheet
// semantics); mutating width/hidden in place is the job of
// `set /Sheet/col[X]`.
// CONSISTENCY(add-row-col-shift): mirror AddRow's positional-insert gate.
// Validate EVERY property BEFORE the structural shift: a parse failure
// after ShiftColumnsRight left the shift applied ("Error" + data moved
// one column right anyway) and an empty <cols/> shell on disk —
// schema-invalid (cols requires >= 1 col child), so a REJECTED add
// corrupted a previously-fine file (0x800A03EC in real Excel).
bool hasColWidth = properties.TryGetValue("width", out var widthStr) && !string.IsNullOrWhiteSpace(widthStr);
double parsedColWidth = hasColWidth ? ParseColWidthChars(widthStr!) : 0;
bool hasColHidden = properties.TryGetValue("hidden", out var addColHidden);
byte? parsedColOutline = null;
if (properties.TryGetValue("outline", out var addColOutline)
|| properties.TryGetValue("outlinelevel", out addColOutline)
|| properties.TryGetValue("group", out addColOutline))
{
if (!byte.TryParse(addColOutline, out var addColOutlineVal) || addColOutlineVal > 7)
throw new ArgumentException($"Invalid 'outline' value: '{addColOutline}'. Expected an integer 0-7 (outline/group level).");
parsedColOutline = addColOutlineVal;
}
bool colNeedsShift = index.HasValue || !string.IsNullOrEmpty(colLetterProp);
if (colNeedsShift)
{
ShiftColumnsRight(colWorksheet, insertColIdx);
DeleteCalcChainIfPresent();
}
// CONSISTENCY(add-set-symmetry): always materialize a <col> element so
// Get/Query can find the column even when no width/hidden was supplied.
// Width/Hidden are attached only when the caller provides them.
{
var ws = GetSheet(colWorksheet);
var columns = ws.GetFirstChild<Columns>() ?? ws.PrependChild(new Columns());
// Idempotent: if a Column with exact Min==Max==insertColIdx already exists,
// update it rather than appending a duplicate.View on GitHub (pinned to 1ced45e900)
Solutions
- Supply an integer between 0 and 7 for the outline/outlinelevel/group property.
- Omit the outline property entirely if you do not need column grouping (parsedColOutline stays null and no outline attribute is written).
- If you meant column width, use the width property instead (e.g. width=12).
Example fix
// before
props["outline"] = "8";
handler.Add("/Sheet1", "col", null, props);
// after
props["outline"] = "7"; // max nesting depth
handler.Add("/Sheet1", "col", null, props); Defensive patterns
Strategy: validation
Validate before calling
if (props.TryGetValue("outline", out var o) && (!byte.TryParse(o, out var ov) || ov > 7))
throw new ArgumentOutOfRangeException(nameof(props), $"outline must be 0-7, got {o}");
handler.Add("/Sheet1", "col", null, props); Type guard
static bool IsValidOutline(string? value) => byte.TryParse(value, out var v) && v <= 7;
Prevention
- Clamp outline values to 0-7 before adding them to the properties dictionary.
- Use a typed configuration object (int with range attributes) and convert to the string dictionary at the boundary.
- Omit the outline key when no grouping is needed rather than passing a sentinel.
When it happens
Trigger: Adding a column with properties["outline"]="8", properties["group"]="-1", properties["outlinelevel"]="high", or any non-numeric string. The check is byte.TryParse followed by a >7 comparison, so negative signs, decimals, and out-of-range integers all fail.
Common situations: User assumes outline level is 1-based and unbounded and passes a large nesting depth. Passing "0" to clear grouping works, but passing "" or whitespace fails. Copying a column-width style value into the outline field by mistake.
Related errors
- Anchor sheet '{aSegs[0]}' must match target sheet '{colSheet
- Invalid 'row' value: '{rbRowIdx}'. Row breaks must be betwee
- Invalid 'col' value: '{cbColStr}'. Column breaks must be bet
- Parent path must be /SheetName/CellRef for adding a run
- Sheet not found: {runSheetName}
AI-assisted analysis of iOfficeAI/OfficeCLI@1ced45e900 (2026-08-13).
Data as JSON: /api/errors/3c328c32e45e6802.
Report an issue: GitHub.