iOfficeAI/OfficeCLI · error · ArgumentException

Invalid crop '{cropAll}'. Expected four comma-separated perc

Error message

Invalid crop '{cropAll}'. Expected four comma-separated percentages in l,t,r,b order (e.g. '10,15,5,20').

What it means

ParseSrcRect's 'crop' composite branch accepts 'l,t,r,b' as exactly four comma-separated percentages (the exact form Get emits, supported so dump->batch replay works). If there are not exactly four parts or any part fails ParseCropPercent, it throws. Order is left, top, right, bottom. This branch only runs when crop has no '=' (the key form routes to srcRect).

Source

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

                anyParsed = true;
            }
            if (!anyParsed)
                throw new ArgumentException(
                    $"Invalid srcRect '{compound}'. Expected 'l=10,r=10,t=5,b=5' (any subset; values are percent 0-100). "
                    + "For raw l/t/r/b numbers use cropLeft/cropTop/cropRight/cropBottom keys.");
        }
        // CONSISTENCY(picture-crop): bare composite `crop=l,t,r,b` — the exact
        // form Get emits (and pptx Add already accepts). Without it, dump→batch
        // replay warned UNSUPPORTED and silently dropped the srcRect.
        if (properties.TryGetValue("crop", out var cropAll) && !string.IsNullOrWhiteSpace(cropAll)
            && !cropAll.Contains('='))
        {
            var cropParts = cropAll.Split(',');
            var cropVals = cropParts.Length == 4
                ? cropParts.Select(ParseCropPercent).ToArray()
                : null;
            if (cropVals == null || !cropVals.All(v => v.HasValue))
                throw new ArgumentException(
                    $"Invalid crop '{cropAll}'. Expected four comma-separated percentages in l,t,r,b order (e.g. '10,15,5,20').");
            l = cropVals[0]; t = cropVals[1]; r = cropVals[2]; b = cropVals[3];
        }
        foreach (var (key, fld) in new[] { ("crop.l", "l"), ("crop.r", "r"), ("crop.t", "t"), ("crop.b", "b") })
        {
            if (properties.TryGetValue(key, out var vs) && !string.IsNullOrWhiteSpace(vs))
            {
                var v = ParseCropPercent(vs);
                if (!v.HasValue) continue;
                switch (fld) { case "l": l = v; break; case "r": r = v; break; case "t": t = v; break; case "b": b = v; break; }
            }
        }
        // CONSISTENCY(picture-crop): Office-API-style `cropLeft`/`cropRight`
        // /`cropTop`/`cropBottom` aliases. Accept fraction (<=1 → *100%) or
        // percent (>1 → as-is); e.g. `cropLeft=0.1` and `cropLeft=10` both
        // mean 10% crop from left.
        foreach (var (key, fld) in new[] { ("cropLeft", "l"), ("cropRight", "r"), ("cropTop", "t"), ("cropBottom", "b") })
        {

View on GitHub (pinned to 1ced45e900)

Solutions

  1. Provide exactly four percentages in l,t,r,b order: crop=10,15,5,20.
  2. For partial crops use the per-side keys crop.l/crop.t/crop.r/crop.b.
  3. Round-trip via Get to obtain the canonical crop string and replay it verbatim.
  4. Validate the part count and numeric parse before calling Add.

Example fix

// before
props["crop"] = "10,15,5";      // only three -> throw
props["crop"] = "10;15;5;20";   // wrong separator -> throw

// after
props["crop"] = "10,15,5,20";   // exactly four, l,t,r,b
// or partial:
props["crop.l"] = "10";
props["crop.r"] = "5";
Defensive patterns

Strategy: validation

Validate before calling

static bool IsValidCropComposite(string s)
{
    var parts = s.Split(',');
    return parts.Length == 4
        && parts.All(p => int.TryParse(p.Trim(), out var v) && v >= 0 && v <= 100);
}

if (!string.IsNullOrWhiteSpace(crop) && !crop.Contains('=') && !IsValidCropComposite(crop))
    throw new ArgumentException($"Bad crop '{crop}'; expected four l,t,r,b percentages");

Type guard

static bool IsValidCropComposite(string s) =>
    s.Split(',') is { Length: 4 } parts
    && parts.All(p => int.TryParse(p.Trim(), out var v) && v is >= 0 and <= 100);

Prevention

When it happens

Trigger: crop=10,15,5 (only three); crop=10,abc,5,20 (non-numeric); crop=10;15;5;20 (semicolon separator); crop=10,15,5,20,1 (five values).

Common situations: Truncated crop string from a manual edit; locale using ';' as list separator; wrong element count or wrong order.

Related errors


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