iOfficeAI/OfficeCLI · error · ArgumentException

Row break index {rbIdx} out of range (1-{breaks.Count})

Error message

Row break index {rbIdx} out of range (1-{breaks.Count})

What it means

Thrown for /SheetName/rowbreak[N] when N is outside the 1-based range [1, <rowBreaks.Count>]. Row breaks (manual horizontal page breaks) live in the worksheet's <rowBreaks> element; if there are none the valid range is 1-0 and any index is rejected, including rowbreak[0].

Source

Thrown at src/officecli/Handlers/Excel/ExcelHandler.Query.cs:467

        // BUG-R41-F2: reject cell reference segments that contain control characters
        // (e.g. \n, \r, \t). Without this check, "A1\n" passes the cell-ref regex
        // (Regex `$` matches before trailing \n in .NET) and resolves to a ghost cell.
        var cellRef = segments[1];
        if (cellRef.Any(c => c < ' ' && c != '\t' || c == '\x7f'))
            throw new ArgumentException(
                $"Cell reference '{cellRef.Replace("\n", "\\n").Replace("\r", "\\r")}' contains invalid control characters. " +
                $"Expected a clean cell address like 'A1' or 'B2'.");

        // Page break path: /Sheet1/rowbreak[N] or /Sheet1/colbreak[N]
        var rbMatch = Regex.Match(cellRef, @"^rowbreak\[(\d+)\]$", RegexOptions.IgnoreCase);
        if (rbMatch.Success)
        {
            var rbIdx = int.Parse(rbMatch.Groups[1].Value);
            var rowBreaks = GetSheet(worksheet).GetFirstChild<RowBreaks>();
            var breaks = rowBreaks?.Elements<Break>().ToList() ?? new();
            if (rbIdx < 1 || rbIdx > breaks.Count)
                throw new ArgumentException($"Row break index {rbIdx} out of range (1-{breaks.Count})");
            var brk = breaks[rbIdx - 1];
            var rbNode = new DocumentNode
            {
                Path = path, Type = "rowbreak",
                Format = { ["row"] = brk.Id?.Value ?? 0u, ["manual"] = brk.ManualPageBreak?.Value ?? false }
            };
            // Restricted-span page break (<brk min max>): surface a non-default
            // column span so dump→replay reproduces it. Full-width default
            // (min 0 / max 16383) is omitted to keep the readback clean.
            if (brk.Min?.Value is { } rbMin && rbMin > 0) rbNode.Format["min"] = (int)rbMin;
            if (brk.Max?.Value is { } rbMax && rbMax != 16383u) rbNode.Format["max"] = (int)rbMax;
            return rbNode;
        }
        var cbMatch = Regex.Match(cellRef, @"^colbreak\[(\d+)\]$", RegexOptions.IgnoreCase);
        if (cbMatch.Success)
        {
            var cbIdx = int.Parse(cbMatch.Groups[1].Value);
            var colBreaks = GetSheet(worksheet).GetFirstChild<ColumnBreaks>();

View on GitHub (pinned to 1ced45e900)

Solutions

  1. Confirm the sheet actually has manual row breaks before indexing.
  2. Use a 1-based index within [1, count]; there is no index 0.
  3. Wrap Get in try/catch(ArgumentException) and read the valid range from the message.

Example fix

// before
var rb = handler.Get("/Sheet1/rowbreak[3]"); // throws if <3 breaks

// after
DocumentNode? GetRowBreak(ExcelHandler h, string sheet, int n) {
  try { return h.Get($"/{sheet}/rowbreak[{n}]"); }
  catch (ArgumentException) { return null; }
}
Defensive patterns

Strategy: try-catch

Type guard

static int? ElementIndex(string cellRef, string element)
{
    var m = Regex.Match(cellRef, $@"^{Regex.Escape(element)}\[(\d+)$", RegexOptions.IgnoreCase);
    return m.Success && int.TryParse(m.Groups[1].Value, out var i) ? i : null;
} // shape/1-based check only — not a range check

Try / catch

try { return handler.Get($"/{sheet}/rowbreak[{n}]"); }
catch (ArgumentException ex) { /* ex.Message carries the valid 1-N range */ return null; }

Prevention

When it happens

Trigger: handler.Get("/Sheet1/rowbreak[3]") on a sheet with fewer than 3 manual row page breaks, or rowbreak[1] on a sheet with no row breaks at all. Using a 0-based index (rowbreak[0]).

Common situations: Assuming a sheet has page breaks because it was imported from a print-formatted workbook. Off-by-one from zero-based indexing. Hard-coded break indices after the file was edited and breaks removed.

Related errors


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