iOfficeAI/OfficeCLI · error · ArgumentException

Column index {cIdx} out of range (1..{tCols?.Count ?? 0})

Error message

Column index {cIdx} out of range (1..{tCols?.Count ?? 0})

What it means

Thrown for /Sheet/table[N]/columns[M] when M exceeds the table's TableColumn count (1-based), or when the table has no <tableColumns> element at all. The message reports the valid column range (1..count, or 1..0 if none).

Source

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

            var tableIdx = int.Parse(tableMatch.Groups[1].Value);
            return TableToNode(sheetNameFromPath, worksheet, tableIdx, depth);
        }

        // Table column path: /Sheet1/table[N]/columns[M] or /column[M]
        var tableColMatch = Regex.Match(cellRef,
            @"^table\[(\d+)\]/(?:columns|column)\[(\d+)\]$", RegexOptions.IgnoreCase);
        if (tableColMatch.Success)
        {
            var tIdx = int.Parse(tableColMatch.Groups[1].Value);
            var cIdx = int.Parse(tableColMatch.Groups[2].Value);
            var tParts = worksheet.TableDefinitionParts.ToList();
            if (tIdx < 1 || tIdx > tParts.Count)
                throw new ArgumentException($"Table index {tIdx} out of range (1..{tParts.Count})");
            var tbl = tParts[tIdx - 1].Table
                ?? throw new ArgumentException($"Table {tIdx} has no definition");
            var tCols = tbl.GetFirstChild<TableColumns>()?.Elements<TableColumn>().ToList();
            if (tCols == null || cIdx < 1 || cIdx > tCols.Count)
                throw new ArgumentException($"Column index {cIdx} out of range (1..{tCols?.Count ?? 0})");
            var tCol = tCols[cIdx - 1];
            var tcNode = new DocumentNode
            {
                Path = $"/{sheetNameFromPath}/table[{tIdx}]/columns[{cIdx}]",
                Type = "tableColumn",
                Text = tCol.Name?.Value ?? ""
            };
            tcNode.Format["name"] = tCol.Name?.Value ?? "";
            if (tCol.Id?.Value != null) tcNode.Format["id"] = tCol.Id.Value;
            if (tCol.TotalsRowFunction?.HasValue == true)
                // Open XML SDK v3 EnumValue<T>.ToString() returns
                // "TotalsRowFunctionValues { }" — use InnerText for the
                // OOXML-canonical lowercase token. CONSISTENCY(enum-innertext).
                tcNode.Format["totalFunction"] = tCol.TotalsRowFunction.InnerText;
            if (tCol.TotalsRowLabel?.Value != null)
                tcNode.Format["totalLabel"] = tCol.TotalsRowLabel.Value;
            var ccf = tCol.CalculatedColumnFormula?.Text;
            if (!string.IsNullOrEmpty(ccf)) tcNode.Format["formula"] = ccf;

View on GitHub (pinned to 1ced45e900)

Solutions

  1. Use a 1-based index in [1, columnCount].
  2. Read the table's column list first to learn the count.
  3. try/catch(ArgumentException) and read the (1..N) range from the message.

Example fix

// before
var col = handler.Get("/Sheet1/table[1]/columns[5]"); // throws if <5 columns

// after
try { var col = handler.Get("/Sheet1/table[1]/columns[5]"); }
catch (ArgumentException) { /* column index invalid */ }
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;
}

Try / catch

try { return handler.Get("/Sheet1/table[1]/columns[5]"); }
catch (ArgumentException ex) { /* ex.Message carries the valid (1..N) column range */ return null; }

Prevention

When it happens

Trigger: handler.Get("/Sheet1/table[1]/columns[5]") on a table with fewer than 5 columns. columns[0]. A table whose <tableColumns> was stripped.

Common situations: Hard-coded column index after columns were added or removed. Zero-based indexing. Mismatch between the table's actual columns and a cached schema.

Related errors


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