iOfficeAI/OfficeCLI · error · ArgumentException

Picture/shape {name} must be positive (got '{value}').

Error message

Picture/shape {name} must be positive (got '{value}').

What it means

Thrown by ParseAnchorDimension when a plain-integer width/height parses but is <= 0. Width/height as cell counts must be strictly positive; zero or negative would produce an invalid TO marker (cx=0/cy=0 or negative spans) that Excel rejects on open. The guard is symmetric with ParseAnchorDimensionEmu's negative-int guard (R30-1).

Source

Thrown at src/officecli/Handlers/Excel/ExcelHandler.Helpers.Drawing.cs:1449

    }

    /// <summary>
    /// Parse a width/height anchor value that is either a plain integer
    /// cell-count ("3", "5") or a unit-qualified size ("6cm", "2in", "72pt").
    /// Unit-qualified values are converted to an approximate cell count using
    /// Excel's default ~64px (~0.66cm) column width and ~15pt row height.
    /// CONSISTENCY(ole-width-units): Picture/Drawing elsewhere accept ParseEmu;
    /// anchor.x/y stay as cell coordinates, but width/height tolerate EMU units.
    /// </summary>
    private static int ParseAnchorDimension(string value, string name)
    {
        if (int.TryParse(value, out var plainInt))
        {
            // R30-1: negative cell-count is meaningless and silently
            // produced an invalid file. Reject up front. CONSISTENCY with
            // ParseAnchorDimensionEmu's negative-int guard.
            if (plainInt <= 0)
                throw new ArgumentException($"Picture/shape {name} must be positive (got '{value}').");
            return plainInt;
        }

        // Not a plain integer — treat as EMU-convertible size string.
        long emu;
        try
        {
            emu = OfficeCli.Core.EmuConverter.ParseEmu(value);
        }
        catch
        {
            throw new ArgumentException($"Expected an integer cell count or a unit-qualified size (e.g. '6cm', '2in') for {name}, got '{value}'.");
        }
        // R30-1: unit-qualified negative ("-2in") parses to a negative
        // EMU; reject so the shape branch matches picture behavior.
        if (emu <= 0)
            throw new ArgumentException($"Picture/shape {name} must be positive (got '{value}').");

View on GitHub (pinned to 1ced45e900)

Solutions

  1. Pass a positive integer cell count: width=3.
  2. If you meant 'size to content', use a twoCell anchor with anchor='B2:D2' so the span is implied by the cell range.
  3. Clamp computed values to >= 1 before passing.
  4. Use a unit-qualified positive size: width='2in'.

Example fix

// before
shape width=0
// after
shape width=3
Defensive patterns

Strategy: validation

Validate before calling

bool IsValidDimensionInt(string value)
    => int.TryParse(value, out var i) && i > 0;

Type guard

static bool IsPositiveCellCount(string s)
    => int.TryParse(s, out var i) && i > 0;

Try / catch

try { ParseAnchorDimension(value, "width"); }
catch (ArgumentException ex) when (ex.Message.Contains("must be positive"))
{
    // default to a sensible positive cell count, or surface a user error
}

Prevention

When it happens

Trigger: Passing width=0, height=-5, or width=-1 as bare integers. Zero is rejected because a zero-span anchor is meaningless; the unit-qualified zero/negative case is handled separately at line 1466.

Common situations: Defaulting an unknown width to 0; sign errors in computed dimensions; expecting width=0 to mean 'auto' (it does not - use a unit-qualified or cell-range anchor instead).

Related errors


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