iOfficeAI/OfficeCLI · error · ArgumentException

Before anchor not found: {position.Before}

Error message

Before anchor not found: {position.Before}

What it means

Thrown when moving a whole sheet with --before where the anchor sheet named in position.Before is not in the <sheets> catalog. Same guard as the --after case: the handler needs a real sibling to insert before, and an unknown anchor name stops the move.

Source

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

            // 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}";

            // localSheetId on <definedName> is a 0-based position into
            // <sheets>; capture the pre-move order so scoped names can be
            // remapped to the sheets' new positions after the reorder.
            var preMoveOrder = sheets.Elements<Sheet>().ToList();

            sheetEl.Remove();

View on GitHub (pinned to 1ced45e900)

Solutions

  1. Verify the anchor sheet name against the live <sheets> list before calling Move.
  2. Fall back to InsertPosition.AtIndex(n) for an absolute target.
  3. Re-read the path from the current workbook if sheets were edited in another session.

Example fix

// before
h.Move("/Sheet1", null, InsertPosition.BeforeElement("/Finale")); // 'Finale' typo for 'Final'
// after
h.Move("/Sheet1", null, InsertPosition.BeforeElement("/Final"));
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?.Before is { } b && !sheets.Any(s => s.Equals(AnchorSheet(b), StringComparison.OrdinalIgnoreCase)))
    throw new InvalidOperationException($"--before anchor sheet '{b}' does not exist");

Try / catch

try { handler.Move("/Sheet1", null, InsertPosition.BeforeElement(anchor)); }
catch (ArgumentException ex) when (ex.Message.StartsWith("Before anchor not found"))
{ /* list sheets and let the user pick a valid before-anchor */ }

Prevention

When it happens

Trigger: Move("/Sheet1", null, InsertPosition.BeforeElement("/Missing")) where 'Missing' is absent; misspelled anchor; anchor sheet removed after the path was built.

Common situations: Stale anchor path; renamed target sheet; referring to a hidden/very-hidden sheet name that differs from the catalog entry.

Related errors


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