iOfficeAI/OfficeCLI · error · ArgumentException
Invalid crop ' '. Expected four comma-separated percentages…
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).
Solutions
- Provide exactly four percentages in l,t,r,b order: crop=10,15,5,20.
- For partial crops use the per-side keys crop.l/crop.t/crop.r/crop.b.
- Round-trip via Get to obtain the canonical crop string and replay it verbatim.
- 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
- Provide exactly four comma-separated percentages in l,t,r,b order.
- Use crop.l/crop.t/crop.r/crop.b keys for partial crops.
- Use the srcRect key form for explicit l/r/t/b assignment.
- Replay the exact crop string Get emits to avoid reformatting mistakes.
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
- Invalid srcRect ' '. Expected 'l=10,r=10,t=5,b=5' (any…
- Picture/shape is out of range for a oneCell/absolute…
- Anchor cell ' ' is outside Excel's grid (A1..XFD1048576).
- Defined name ' ' collides with the table name ' '. Excel…
- DefinedName ' ' not found
AI-assisted analysis of iOfficeAI/OfficeCLI@1ced45e900 (2026-08-13).
Data as JSON: /api/errors/a28663fa48ded3d4.
Report an issue: GitHub.
Appendix: 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)