iOfficeAI/OfficeCLI · error · ArgumentException

Swap requires element paths (e.g. /Sheet1/row[1])

Error message

Swap requires element paths (e.g. /Sheet1/row[1])

What it means

Thrown by Swap when one of the two paths has no second segment after splitting (seg1 or seg2 Length < 2), i.e. a path like "/Sheet1" without the '/row[N]' part. Swap exchanges two row elements, so both arguments must be full element paths.

Source

Thrown at src/officecli/Handlers/Excel/ExcelHandler.Add.cs:688

        {
            row.RowIndex = newIdx;
            foreach (var cell in row.Elements<Cell>())
            {
                if (cell.CellReference?.Value == null) continue;
                var (col, _) = ParseCellReference(cell.CellReference.Value);
                cell.CellReference = $"{col}{newIdx}";
            }
            newIdx++;
        }
    }

    public (string NewPath1, string NewPath2) Swap(string path1, string path2)
    {
        // Parse both paths: /SheetName/row[N]
        var seg1 = path1.TrimStart('/').Split('/', 2);
        var seg2 = path2.TrimStart('/').Split('/', 2);
        if (seg1.Length < 2 || seg2.Length < 2)
            throw new ArgumentException("Swap requires element paths (e.g. /Sheet1/row[1])");
        if (seg1[0] != seg2[0])
            throw new ArgumentException("Cannot swap elements across different sheets");

        var sheetName = seg1[0];
        var worksheet = FindWorksheet(sheetName)
            ?? throw new ArgumentException($"Sheet not found: {sheetName}");
        var sheetData = GetSheet(worksheet).GetFirstChild<SheetData>()
            ?? throw new ArgumentException("Sheet has no data");

        var rowMatch1 = Regex.Match(seg1[1], @"^row\[(\d+)\]$");
        var rowMatch2 = Regex.Match(seg2[1], @"^row\[(\d+)\]$");
        if (!rowMatch1.Success || !rowMatch2.Success)
            throw new ArgumentException("Swap only supports row[N] elements in Excel");

        var allRows = sheetData.Elements<Row>().ToList();
        var idx1 = int.Parse(rowMatch1.Groups[1].Value);
        var idx2 = int.Parse(rowMatch2.Groups[1].Value);
        var row1 = (idx1 >= 1 && idx1 <= allRows.Count ? allRows[idx1 - 1] : null)

View on GitHub (pinned to 1ced45e900)

Solutions

  1. Pass full row paths for both arguments: "/<sheet>/row[<N>]".
  2. Construct swap paths from verified row nodes, not sheet nodes.
  3. If you meant to reorder sheets, use Move on a sheet-level path instead.

Example fix

// before
h.Swap("/Sheet1", "/Sheet1/row[2]"); // first arg has no element segment
// after
h.Swap("/Sheet1/row[1]", "/Sheet1/row[2]");
Defensive patterns

Strategy: validation

Validate before calling

static bool IsElementPath(string p) => p.TrimStart('/').Split('/', 2).Length >= 2;
if (!IsElementPath(path1) || !IsElementPath(path2))
    throw new ArgumentException("Swap requires full /sheet/row[N] paths for both arguments");

Type guard

static bool IsSwapCandidate(string p)
{
    var segs = p.TrimStart('/').Split('/', 2);
    return segs.Length >= 2 && System.Text.RegularExpressions.Regex.IsMatch(segs[1], @"^row\[\d+\]$");
}

Prevention

When it happens

Trigger: Swap("/Sheet1", "/Sheet1/row[2]"); a path truncated to just the sheet; passing a sheet-level path where a row path is required.

Common situations: Building swap args from a sheet name instead of a row path; partial path construction; confusing Swap (element exchange) with sheet reorder.

Related errors


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