{"record":{"id":"3c328c32e45e6802","repo":"iOfficeAI/OfficeCLI","slug":"invalid-outline-value-addcoloutline-expect","errorCode":null,"errorMessage":"Invalid 'outline' value: '{addColOutline}'. Expected an integer 0-7 (outline/group level).","messagePattern":"Invalid 'outline' value: '(.+?)'\\. Expected an integer 0-7 \\(outline/group level\\)\\.","errorType":"validation","errorClass":"System.ArgumentException","httpStatus":null,"severity":"error","filePath":"src/officecli/Handlers/Excel/ExcelHandler.Add.Cells.cs","lineNumber":1133,"sourceCode":"        // shift, never gated on stored column width (standard spreadsheet\n        // semantics); mutating width/hidden in place is the job of\n        // `set /Sheet/col[X]`.\n        // CONSISTENCY(add-row-col-shift): mirror AddRow's positional-insert gate.\n        // Validate EVERY property BEFORE the structural shift: a parse failure\n        // after ShiftColumnsRight left the shift applied (\"Error\" + data moved\n        // one column right anyway) and an empty <cols/> shell on disk —\n        // schema-invalid (cols requires >= 1 col child), so a REJECTED add\n        // corrupted a previously-fine file (0x800A03EC in real Excel).\n        bool hasColWidth = properties.TryGetValue(\"width\", out var widthStr) && !string.IsNullOrWhiteSpace(widthStr);\n        double parsedColWidth = hasColWidth ? ParseColWidthChars(widthStr!) : 0;\n        bool hasColHidden = properties.TryGetValue(\"hidden\", out var addColHidden);\n        byte? parsedColOutline = null;\n        if (properties.TryGetValue(\"outline\", out var addColOutline)\n            || properties.TryGetValue(\"outlinelevel\", out addColOutline)\n            || properties.TryGetValue(\"group\", out addColOutline))\n        {\n            if (!byte.TryParse(addColOutline, out var addColOutlineVal) || addColOutlineVal > 7)\n                throw new ArgumentException($\"Invalid 'outline' value: '{addColOutline}'. Expected an integer 0-7 (outline/group level).\");\n            parsedColOutline = addColOutlineVal;\n        }\n\n        bool colNeedsShift = index.HasValue || !string.IsNullOrEmpty(colLetterProp);\n        if (colNeedsShift)\n        {\n            ShiftColumnsRight(colWorksheet, insertColIdx);\n            DeleteCalcChainIfPresent();\n        }\n\n        // CONSISTENCY(add-set-symmetry): always materialize a <col> element so\n        // Get/Query can find the column even when no width/hidden was supplied.\n        // Width/Hidden are attached only when the caller provides them.\n        {\n            var ws = GetSheet(colWorksheet);\n            var columns = ws.GetFirstChild<Columns>() ?? ws.PrependChild(new Columns());\n            // Idempotent: if a Column with exact Min==Max==insertColIdx already exists,\n            // update it rather than appending a duplicate.","sourceCodeStart":1115,"sourceCodeEnd":1151,"githubUrl":"https://github.com/iOfficeAI/OfficeCLI/blob/1ced45e900782c5083ed550ddf328ee974e425e7/src/officecli/Handlers/Excel/ExcelHandler.Add.Cells.cs#L1115-L1151","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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)."],"exampleFix":"// before\nprops[\"outline\"] = \"8\";\nhandler.Add(\"/Sheet1\", \"col\", null, props);\n\n// after\nprops[\"outline\"] = \"7\"; // max nesting depth\nhandler.Add(\"/Sheet1\", \"col\", null, props);","handlingStrategy":"validation","validationCode":"if (props.TryGetValue(\"outline\", out var o) && (!byte.TryParse(o, out var ov) || ov > 7))\n    throw new ArgumentOutOfRangeException(nameof(props), $\"outline must be 0-7, got {o}\");\nhandler.Add(\"/Sheet1\", \"col\", null, props);","typeGuard":"static bool IsValidOutline(string? value) => byte.TryParse(value, out var v) && v <= 7;","tryCatchPattern":null,"preventionTips":["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."],"tags":["excel","ooxml","add-col","outline","range-validation","argument"],"backgroundTag":null,"analyzedSha":"1ced45e900782c5083ed550ddf328ee974e425e7","analyzedAt":"2026-08-13T13:01:07.193Z","schemaVersion":2},"datasetVersion":"2026-08-13T14:17:21.547Z"}