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

  1. Supply an integer between 0 and 7 for the outline/outlinelevel/group property.
  2. Omit the outline property entirely if you do not need column grouping (parsedColOutline stays null and no outline attribute is written).
  3. 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

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


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