iOfficeAI/OfficeCLI · error · ArgumentException

Invalid anchor: '{picAnchorRaw}'. Expected e.g. 'B2', 'B2:E6

Error message

Invalid anchor: '{picAnchorRaw}'. Expected e.g. 'B2', 'B2:E6', or one of 'oneCell'/'twoCell'/'absolute'.

What it means

Thrown by AddPicture when the 'anchor' property is present, is not a recognized anchorMode token (oneCell/twoCell/absolute), and fails to parse as a cell-range reference via TryParseCellRangeAnchor. The picture branch first checks IsAnchorModeToken; only if that returns false does it attempt cell-range parsing. This is the broadest anchor error message because pictures accept three input shapes: cell ('B2'), range ('B2:E6'), or mode token ('oneCell').

Source

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

        // DrawingsPart (and possibly the media blob) was already attached,
        // leaving an empty <xdr:wsDr/> container plus orphaned xl/media
        // bytes in the saved file even though the add reported an error.
        var (xlImgStream, imgPartType) = OfficeCli.Core.ImageSource.Resolve(imgPath);
        using var xlImgDispose = xlImgStream;

        var picAnchorRaw = properties.GetValueOrDefault("anchor");
        var picAnchorModeExplicit = properties.GetValueOrDefault("anchorMode");
        bool picHasRange = false;
        int picRangeFromCol = 0, picRangeFromRow = 0, picRangeToCol = -1, picRangeToRow = -1;
        // `anchor=` is either a cell-range ("B2" / "B2:E6") or an
        // anchorMode token ("oneCell"/"twoCell"/"absolute"). Prefer the
        // cell-range interpretation; fall back to mode-token only when
        // the value is a recognized token. Explicit `anchorMode=` wins
        // the mode selection regardless.
        if (!string.IsNullOrWhiteSpace(picAnchorRaw) && !IsAnchorModeToken(picAnchorRaw))
        {
            if (!TryParseCellRangeAnchor(picAnchorRaw, out picRangeFromCol, out picRangeFromRow, out picRangeToCol, out picRangeToRow))
                throw new ArgumentException($"Invalid anchor: '{picAnchorRaw}'. Expected e.g. 'B2', 'B2:E6', or one of 'oneCell'/'twoCell'/'absolute'.");
            picHasRange = true;
            if (properties.ContainsKey("width") | properties.ContainsKey("height")
                | properties.ContainsKey("x") | properties.ContainsKey("y"))
                Console.Error.WriteLine(
                    "Warning: 'x'/'y'/'width'/'height' are ignored when 'anchor' is a cell range (anchor defines the full rectangle).");
        }
        var picAnchorMode = (picAnchorModeExplicit
            ?? (picHasRange ? "twoCell" : picAnchorRaw)
            ?? "twoCell").Trim().ToLowerInvariant();

        var picDrawingsPart = picWorksheet.DrawingsPart
            ?? picWorksheet.AddNewPart<DrawingsPart>();

        if (picDrawingsPart.WorksheetDrawing == null)
        {
            picDrawingsPart.WorksheetDrawing = new XDR.WorksheetDrawing();
            picDrawingsPart.WorksheetDrawing.Save();

View on GitHub (pinned to 1ced45e900)

Solutions

  1. Use a single cell like 'B2', a colon-separated range like 'B2:E6', or one of the mode tokens 'oneCell'/'twoCell'/'absolute'.
  2. Drop anchor= and use x=/y=/width=/height= for numeric positioning.
  3. Check for typos in mode-token names (case-insensitive, but must match exactly: oneCell, twoCell, absolute).
  4. Ensure range separators are colons (:), not commas or semicolons.

Example fix

// before
add /Sheet1 --type picture --src logo.png --anchor "top-left"
// after
add /Sheet1 --type picture --src logo.png --anchor "B2:E6"
Defensive patterns

Strategy: validation

Validate before calling

// Validate picture anchor before the add call
if (properties.TryGetValue("anchor", out var picAnchor) && !string.IsNullOrWhiteSpace(picAnchor))
{
    var isModeToken = picAnchor.Trim().ToLowerInvariant() is "onecell" or "twocell" or "absolute";
    var isCellRange = System.Text.RegularExpressions.Regex.IsMatch(
        picAnchor, @"^[A-Z]+\d+(:[A-Z]+\d+)?$", RegexOptions.IgnoreCase);
    if (!isModeToken && !isCellRange)
        throw new InvalidOperationException(
            $"Invalid picture anchor '{picAnchor}'. Expected a cell ('B2'), range ('B2:E6'), " +
            "or mode token ('oneCell'/'twoCell'/'absolute').");
}

Type guard

static bool IsValidPictureAnchor(string? s)
{
    if (string.IsNullOrWhiteSpace(s)) return false;
    var v = s.Trim().ToLowerInvariant();
    if (v is "onecell" or "twocell" or "absolute") return true;
    return System.Text.RegularExpressions.Regex.IsMatch(
        s, @"^[A-Z]+\d+(:[A-Z]+\d+)?$", RegexOptions.IgnoreCase);
}

Try / catch

try { handler.AddPicture(parentPath, type, position, properties); }
catch (ArgumentException ex) when (ex.Message.StartsWith("Invalid anchor:"))
{
    Console.Error.WriteLine($"{ex.Message} Use a cell, range, or mode token.");
}

Prevention

When it happens

Trigger: Setting properties["anchor"] to a value that is neither a recognized mode token nor a valid cell/range. Examples: 'B-2', 'top-left', 'absolute_anchor', 'B2;E6'. If the value IS a mode token, IsAnchorModeToken returns true and no error fires. If it is a cell/range that fails parsing, this error fires.

Common situations: User passes a descriptive word that is not one of the three recognized tokens. User uses wrong separators (semicolon, comma). User copies an anchor from a non-Excel context.

Related errors


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