iOfficeAI/OfficeCLI · error · ArgumentException

After anchor not found: {position.After}

Error message

After anchor not found: {position.After}

What it means

Thrown when moving a whole sheet with --after where the anchor sheet named in position.After is not present in the <sheets> catalog (ExtractAnchorSheetName + OrdinalIgnoreCase lookup failed). The reorder needs a concrete sibling to insert after, so an unknown anchor aborts the move.

Source

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

            // supports --index / --after /Sheet2 / --before /Sheet3.
            var workbook = GetWorkbook();
            var sheets = workbook.GetFirstChild<Sheets>()
                ?? throw new InvalidOperationException("Workbook has no sheets element");
            var sheetEl = sheets.Elements<Sheet>().FirstOrDefault(s =>
                string.Equals(s.Name?.Value, sheetName, StringComparison.OrdinalIgnoreCase))
                ?? throw new ArgumentException($"Sheet not found: {sheetName}");

            // Resolve after/before anchor BEFORE removing sheetEl.
            static string ExtractAnchorSheetName(string raw) =>
                (raw.StartsWith("/") ? raw[1..] : raw).Split('/', 2)[0];

            Sheet? afterAnchor = null, beforeAnchor = null;
            if (position?.After != null)
            {
                var anchorName = ExtractAnchorSheetName(position.After);
                afterAnchor = sheets.Elements<Sheet>().FirstOrDefault(s =>
                    string.Equals(s.Name?.Value, anchorName, StringComparison.OrdinalIgnoreCase))
                    ?? throw new ArgumentException($"After anchor not found: {position.After}");
            }
            else if (position?.Before != null)
            {
                var anchorName = ExtractAnchorSheetName(position.Before);
                beforeAnchor = sheets.Elements<Sheet>().FirstOrDefault(s =>
                    string.Equals(s.Name?.Value, anchorName, StringComparison.OrdinalIgnoreCase))
                    ?? throw new ArgumentException($"Before anchor not found: {position.Before}");
            }
            else if (index == null)
            {
                throw new ArgumentException("One of --index, --after, or --before is required when moving a sheet");
            }

            // Self-move guard: moving a sheet after/before itself is a no-op.
            // Removing first detaches sheetEl, then InsertAfterSelf/InsertBeforeSelf
            // throws "parent is null" and the sheet is lost (data loss).
            if (ReferenceEquals(afterAnchor, sheetEl) || ReferenceEquals(beforeAnchor, sheetEl))
                return $"/{sheetName}";

View on GitHub (pinned to 1ced45e900)

Solutions

  1. Confirm the anchor sheet exists in the current workbook before calling Move.
  2. Use InsertPosition.AtIndex(n) if you only need an absolute position.
  3. Prefer InsertPosition.AfterElement("/<existingSheet>") with a verified name.

Example fix

// before
h.Move("/Sheet1", null, InsertPosition.AfterElement("/SheetX")); // SheetX missing
// after
h.Move("/Sheet1", null, InsertPosition.AfterElement("/Sheet2")); // Sheet2 exists
Defensive patterns

Strategy: validation

Validate before calling

string AnchorSheet(string raw) => (raw.StartsWith("/") ? raw[1..] : raw).Split('/', 2)[0];
var sheets = handler.Get("/", depth: 1).Children.Select(c => c.Name).ToList();
if (pos?.After is { } a && !sheets.Any(s => s.Equals(AnchorSheet(a), StringComparison.OrdinalIgnoreCase)))
    throw new InvalidOperationException($"--after anchor sheet '{a}' does not exist");

Try / catch

try { handler.Move("/Sheet1", null, InsertPosition.AfterElement(anchor)); }
catch (ArgumentException ex) when (ex.Message.StartsWith("After anchor not found"))
{ /* prompt for a valid anchor sheet from the live list */ }

Prevention

When it happens

Trigger: Move("/Sheet1", null, InsertPosition.AfterElement("/Gone")) where 'Gone' is not a sheet; typo in the anchor name; anchor referencing a sheet from a different workbook.

Common situations: Anchor sheet deleted/renamed since the path was captured; copy-paste of a stale path; case the user assumed is supported but the name is simply wrong.

Related errors


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