iOfficeAI/OfficeCLI · error · ArgumentException

Anchor sheet '{aSegs[0]}' must match target sheet '{targetSh

Error message

Anchor sheet '{aSegs[0]}' must match target sheet '{targetSheetName}'

What it means

Thrown by the row-anchor resolver when the anchor's sheet segment does not match the target sheet (aSegs[0] != targetSheetName, case-insensitive). Cross-sheet row anchors are rejected: the anchor row must live in the same sheet the row is being moved into, otherwise the resolved position would be meaningless.

Source

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

            // Resolve --before / --after anchors to a 0-based document-order
            // position in the target sheet. Anchor must be /<TargetSheet>/row[K].
            // Resolved BEFORE removing the moved row so the anchor is found by
            // its current position.
            int? targetIndex = index;
            string targetSheetName = string.IsNullOrEmpty(targetParentPath)
                ? sheetName
                : targetParentPath.TrimStart('/').Split('/', 2)[0];
            if (targetIndex == null && position != null && (position.After != null || position.Before != null))
            {
                int FindAnchorRowPos(string anchorPath)
                {
                    var aSegs = anchorPath.TrimStart('/').Split('/', 2);
                    if (aSegs.Length < 2)
                        throw new ArgumentException(
                            $"Anchor must be a row path like /{targetSheetName}/row[K], got: {anchorPath}");
                    if (!aSegs[0].Equals(targetSheetName, StringComparison.OrdinalIgnoreCase))
                        throw new ArgumentException(
                            $"Anchor sheet '{aSegs[0]}' must match target sheet '{targetSheetName}'");
                    var am = Regex.Match(aSegs[1], @"^row\[(\d+)\]$");
                    if (!am.Success)
                        throw new ArgumentException(
                            $"Anchor must be a row path like /{targetSheetName}/row[K], got: {anchorPath}");
                    var anchorRowIdx = uint.Parse(am.Groups[1].Value);
                    var pos = targetSheetData.Elements<Row>().ToList()
                        .FindIndex(r => r.RowIndex?.Value == anchorRowIdx);
                    if (pos < 0)
                        throw new ArgumentException($"Anchor row {anchorRowIdx} not found in {targetSheetName}");
                    return pos;
                }
                if (position.Before != null) targetIndex = FindAnchorRowPos(position.Before);
                else targetIndex = FindAnchorRowPos(position.After!) + 1;
            }

            // If the moved row sits before the anchor in the same sheet,
            // removing it shifts everything (including the anchor) up by one.

View on GitHub (pinned to 1ced45e900)

Solutions

  1. Make the anchor's sheet equal the target sheet (or omit targetParentPath for a same-sheet move and anchor within the source sheet).
  2. Derive targetSheetName from targetParentPath and build the anchor from it.
  3. Use InsertPosition.AtIndex(n) to avoid anchor-sheet coupling entirely.

Example fix

// before
h.Move("/Src/row[1]", "/Dst", InsertPosition.AfterElement("/Src/row[2]")); // anchor sheet != target
// after
h.Move("/Src/row[1]", "/Dst", InsertPosition.AfterElement("/Dst/row[2]"));
Defensive patterns

Strategy: validation

Validate before calling

string targetSheet = string.IsNullOrEmpty(targetParentPath)
    ? sourcePath.TrimStart('/').Split('/', 2)[0]
    : targetParentPath.TrimStart('/').Split('/', 2)[0];
foreach (var anchor in new[] { pos?.After, pos?.Before }.Where(a => a != null)!)
{
    var aSheet = anchor.TrimStart('/').Split('/', 2)[0];
    if (!aSheet.Equals(targetSheet, StringComparison.OrdinalIgnoreCase))
        throw new InvalidOperationException($"Anchor sheet '{aSheet}' must equal target '{targetSheet}'");
}

Prevention

When it happens

Trigger: Moving into Sheet2 but passing InsertPosition.AfterElement("/Sheet1/row[2]"); targetParentPath names a different sheet than the anchor; anchor copied from the source sheet while moving cross-sheet.

Common situations: Cross-sheet move where the user kept the source sheet in the anchor; refactoring a same-sheet call to cross-sheet without updating the anchor.

Related errors


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