{"record":{"id":"2e96a207bb3fab51","repo":"iOfficeAI/OfficeCLI","slug":"row-property-is-required-for-rowbreak","errorCode":null,"errorMessage":"'row' property is required for rowbreak","messagePattern":"'row' property is required for rowbreak","errorType":"validation","errorClass":"System.ArgumentException","httpStatus":null,"severity":"error","filePath":"src/officecli/Handlers/Excel/ExcelHandler.Add.Cells.cs","lineNumber":1331,"sourceCode":"    {\n        var index = position?.Index;\n        // Route to rowbreak or colbreak based on properties\n        if (properties.ContainsKey(\"col\") || properties.ContainsKey(\"column\"))\n            return Add(parentPath, \"colbreak\", position, properties);\n        return Add(parentPath, \"rowbreak\", position, properties);\n    }\n\n    private string AddRowBreak(string parentPath, string type, InsertPosition? position, Dictionary<string, string> properties)\n    {\n        var index = position?.Index;\n        var rbSegments = parentPath.TrimStart('/').Split('/', 2);\n        var rbSheetName = rbSegments[0];\n        var rbWorksheet = FindWorksheet(rbSheetName)\n            ?? throw new ArgumentException($\"Sheet not found: {rbSheetName}\");\n        var rbWs = GetSheet(rbWorksheet);\n\n        var rbRowIdx = uint.Parse(properties.GetValueOrDefault(\"row\") ?? properties.GetValueOrDefault(\"index\")\n            ?? throw new ArgumentException(\"'row' property is required for rowbreak\"));\n        // A break id of 0 or beyond the grid fails the schema's Min/Max\n        // constraints — reject up front instead of writing invalid OOXML.\n        if (rbRowIdx < 1 || rbRowIdx > 1048576)\n            throw new ArgumentException(\n                $\"Invalid 'row' value: '{rbRowIdx}'. Row breaks must be between 1 and 1048576.\");\n\n        var rowBreaks = rbWs.GetFirstChild<RowBreaks>();\n        if (rowBreaks == null)\n        {\n            rowBreaks = new RowBreaks();\n            rbWs.AppendChild(rowBreaks);\n        }\n        // Optional restricted column span (min/max) — mirrors the Set path so a\n        // dump-emitted `add rowbreak row=N min=.. max=..` reproduces a\n        // non-full-width break. Defaults to full width (max 16383) when absent.\n        var rbBreak = new Break { Id = rbRowIdx, Max = 16383u, ManualPageBreak = true };\n        if (properties.TryGetValue(\"min\", out var rbMinS) && uint.TryParse(rbMinS, out var rbMin))\n            rbBreak.Min = rbMin;","sourceCodeStart":1313,"sourceCodeEnd":1349,"githubUrl":"https://github.com/iOfficeAI/OfficeCLI/blob/1ced45e900782c5083ed550ddf328ee974e425e7/src/officecli/Handlers/Excel/ExcelHandler.Add.Cells.cs#L1313-L1349","documentation":"Thrown by AddRowBreak when neither the row nor the index property is present in the properties dictionary. The code uses GetValueOrDefault(\"row\") ?? GetValueOrDefault(\"index\") and throws if both are null. A row break requires a target row number, so omitting it is unrecoverable.","triggerScenarios":"Add type=rowbreak with a properties dictionary that has neither \"row\" nor \"index\" (e.g. only min/max, or empty). Passing \"row\" with an empty string value: GetValueOrDefault returns the empty string, which then fails uint.Parse with a FormatException (a different error), not this one. This throw specifically needs the key absent entirely.","commonSituations":"User copies a colbreak command and forgets to change the property from col to row. Script builds properties conditionally and both branches are skipped. Assuming index defaults to the position's Index (it does not for rowbreak).","solutions":["Add a row property: properties[\"row\"]=\"5\".","The index property is accepted as an alias, so properties[\"index\"]=\"5\" works too.","If you meant a column break, use type=colbreak with col= instead."],"exampleFix":"// before\nhandler.Add(\"/Sheet1\", \"rowbreak\", null, new() { [\"min\"] = \"1\" });\n\n// after\nhandler.Add(\"/Sheet1\", \"rowbreak\", null, new() { [\"row\"] = \"5\", [\"min\"] = \"1\" });","handlingStrategy":"validation","validationCode":"if (!props.ContainsKey(\"row\") && !props.ContainsKey(\"index\"))\n    throw new InvalidOperationException(\"rowbreak requires 'row' or 'index'\");\nhandler.Add(\"/Sheet1\", \"rowbreak\", null, props);","typeGuard":"static bool HasRowbreakTarget(IReadOnlyDictionary<string,string> p)\n    => p.ContainsKey(\"row\") || p.ContainsKey(\"index\");","tryCatchPattern":null,"preventionTips":["Always set row= explicitly when constructing a rowbreak command.","Use a builder that requires the row parameter at compile time.","Distinguish rowbreak (row=) from colbreak (col=) when copying commands."],"tags":["excel","ooxml","rowbreak","missing-property","argument"],"backgroundTag":null,"analyzedSha":"1ced45e900782c5083ed550ddf328ee974e425e7","analyzedAt":"2026-08-13T13:01:07.193Z","schemaVersion":2},"datasetVersion":"2026-08-13T14:17:21.547Z"}