iOfficeAI/OfficeCLI · error · ArgumentException

Invalid range: {range}

Error message

Invalid range: {range}

What it means

GetCellRange requires the range string to split into exactly two colon-separated cell references and throws otherwise. This is the read/range path invoked from Query.cs:946 for DOM-style range reads. A single cell (no colon) or a malformed multi-colon range (A1:B2:C3) both fail here. ParseCellReference/ColumnNameToIndex are then applied to each half, so the two halves must be valid A1 refs.

Source

Thrown at src/officecli/Handlers/Excel/ExcelHandler.Helpers.Cell.cs:347

        var dimParts = range.Split(':');
        if (dimParts.Length != 2) return false;
        var m1 = System.Text.RegularExpressions.Regex.Match(dimParts[0], @"^([A-Z]+)(\d+)$");
        var m2 = System.Text.RegularExpressions.Regex.Match(dimParts[1], @"^([A-Z]+)(\d+)$");
        if (!m1.Success || !m2.Success) return false;
        var c1 = ColumnNameToIndex(m1.Groups[1].Value);
        var c2 = ColumnNameToIndex(m2.Groups[1].Value);
        var r1 = int.Parse(m1.Groups[2].Value);
        var r2 = int.Parse(m2.Groups[2].Value);
        rows = Math.Abs(r2 - r1) + 1;
        cols = Math.Abs(c2 - c1) + 1;
        return true;
    }

    private DocumentNode GetCellRange(string sheetName, SheetData sheetData, string range, int depth, WorksheetPart? part = null)
    {
        var parts = range.Split(':');
        if (parts.Length != 2)
            throw new ArgumentException($"Invalid range: {range}");

        var (startCol, startRow) = ParseCellReference(parts[0]);
        var (endCol, endRow) = ParseCellReference(parts[1]);
        var startColIdx = ColumnNameToIndex(startCol);
        var endColIdx = ColumnNameToIndex(endCol);

        var node = new DocumentNode
        {
            Path = $"/{sheetName}/{range}",
            Type = "range",
            Preview = range
        };

        // Build lookup of existing cells so we can fill empty stubs for missing positions
        var existingCells = new Dictionary<string, Cell>(StringComparer.OrdinalIgnoreCase);
        foreach (var row in sheetData.Elements<Row>())
        {
            var rowIdx = (int)(row.RowIndex?.Value ?? 0);

View on GitHub (pinned to 1ced45e900)

Solutions

  1. Pass a proper two-anchor range 'A1:B2'.
  2. For single cells, use the cell path rather than the range path.
  3. Validate that the string contains exactly one ':' before calling.
  4. Trim whitespace and strip stray characters from the range.

Example fix

// before
handler.Get(path: "/Sheet1/A1", ...);   // single cell -> range split fails

// after
handler.Get(path: "/Sheet1/A1:A1", ...); // valid degenerate range
Defensive patterns

Strategy: validation

Validate before calling

static bool IsRangeRef(string r) =>
    !string.IsNullOrWhiteSpace(r) && r.Split(':').Length == 2;

if (!IsRangeRef(range))
    throw new ArgumentException($"Not a two-anchor range: {range}");

Type guard

static bool IsRangeRef(string r) =>
    r?.Split(':') is { Length: 2 };

Prevention

When it happens

Trigger: Get path '/Sheet1/A1' routed as a range (no colon); range 'A1:B2:C3' (extra colon); range built by string concatenation that dropped one anchor.

Common situations: Passing a single-cell ref where a range is required; query router mishandling a cell vs range; truncation or duplication of the colon during ref assembly.

Related errors


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