{"record":{"id":"658f68e7c01cb273","repo":"iOfficeAI/OfficeCLI","slug":"invalid-margin-value-value-expected-single","errorCode":null,"errorMessage":"Invalid 'margin' value '{value}'. Expected single length (e.g. '4pt', '0.5cm') or 4-CSV 'L,T,R,B'.","messagePattern":"Invalid 'margin' value '(.+?)'\\. Expected single length \\(e\\.g\\. '4pt', '0\\.5cm'\\) or 4-CSV 'L,T,R,B'\\.","errorType":"exception","errorClass":"ArgumentException","httpStatus":null,"severity":"error","filePath":"src/officecli/Handlers/Excel/ExcelHandler.Helpers.Drawing.cs","lineNumber":1347,"sourceCode":"    /// Accepts unit-qualified \"14pt\"/\"0.5cm\"/\"0.2in\"/bare-points for uniform\n    /// inset, OR a 4-CSV \"Lpt,Tpt,Rpt,Bpt\" matching Get's readback format.\n    /// CONSISTENCY(spacing-units): mirrors SpacingConverter usage so that\n    /// margin's input vocabulary matches Get's \"Npt\"/\"L,T,R,B\" output.\n    /// </summary>\n    private static (int L, int T, int R, int B) ParseShapeMarginToEmu(string value)\n    {\n        var parts = (value ?? string.Empty).Split(',', StringSplitOptions.TrimEntries | StringSplitOptions.RemoveEmptyEntries);\n        if (parts.Length == 4)\n        {\n            int Emu(string s) => (int)Math.Round(SpacingConverter.ParsePoints(s) * EmuConverter.EmuPerPoint);\n            return (Emu(parts[0]), Emu(parts[1]), Emu(parts[2]), Emu(parts[3]));\n        }\n        if (parts.Length == 1)\n        {\n            var emu = (int)Math.Round(SpacingConverter.ParsePoints(parts[0]) * EmuConverter.EmuPerPoint);\n            return (emu, emu, emu, emu);\n        }\n        throw new ArgumentException(\n            $\"Invalid 'margin' value '{value}'. Expected single length (e.g. '4pt', '0.5cm') or 4-CSV 'L,T,R,B'.\");\n    }\n\n    private static Drawing.ShapeTypeValues ParseExcelShapePreset(string name)\n    {\n        var key = (name ?? string.Empty).Trim().ToLowerInvariant();\n        if (string.IsNullOrEmpty(key))\n            return Drawing.ShapeTypeValues.Rectangle;\n        if (_shapePresetMap.TryGetValue(key, out var val))\n            return val;\n        // R20-01: Unknown preset falls back to rectangle, but emit a stderr\n        // warning so users notice (silent rect was found by audit). 'custom'\n        // is the common case — it would require a custGeom path which\n        // officecli doesn't expose, so suggest raw-set explicitly.\n        if (key == \"custom\")\n        {\n            Console.Error.WriteLine(\n                \"Warning: preset='custom' requires a custGeom path which officecli does not expose; \" +","sourceCodeStart":1329,"sourceCodeEnd":1365,"githubUrl":"https://github.com/iOfficeAI/OfficeCLI/blob/1ced45e900782c5083ed550ddf328ee974e425e7/src/officecli/Handlers/Excel/ExcelHandler.Helpers.Drawing.cs#L1329-L1365","documentation":"Thrown by the margin parser when the value does not split into exactly 1 or exactly 4 non-empty comma-separated parts. A single part applies the same margin to all four sides; a 4-CSV 'L,T,R,B' sets each side independently. Parts are parsed as lengths via SpacingConverter.ParsePoints (so '4pt', '0.5cm', '0.1in' all work), then converted to EMU.","triggerScenarios":"Passing 2 or 3 values like margin='4pt,2pt' or margin='4pt,2pt,1pt'; using space separation like margin='4pt 2pt 1pt 0' (the whole thing becomes one part that fails point parsing only if it had commas); mixing the single-value and per-side forms; trailing commas producing empty entries that get removed and drop the count below 4.","commonSituations":"Copying CSS 'margin: 4pt 2pt 1pt 0' shorthand (space-separated, not comma); expecting TRBL order like CSS (the parser is L,T,R,B); passing partial per-side values; AI assistants emitting fewer than 4 sides when per-side was intended.","solutions":["Use a single length for uniform margins: margin='4pt'.","Use exactly four comma-separated lengths in L,T,R,B order: margin='4pt,2pt,4pt,2pt'.","Do not use CSS space shorthand or TRBL order; OfficeCLI uses explicit comma-CSV in L,T,R,B.","Remove trailing/leading commas and ensure no empty fields."],"exampleFix":"// before\nshape margin=4pt 2pt 4pt 2pt\n// after\nshape margin=4pt,2pt,4pt,2pt","handlingStrategy":"validation","validationCode":"bool IsValidMargin(string value)\n{\n    var parts = (value ?? string.Empty)\n        .Split(',', StringSplitOptions.TrimEntries | StringSplitOptions.RemoveEmptyEntries);\n    return parts.Length == 1 || parts.Length == 4;\n}","typeGuard":"static bool IsMarginSpec(string s)\n{\n    var n = (s ?? string.Empty)\n        .Split(',', StringSplitOptions.TrimEntries | StringSplitOptions.RemoveEmptyEntries).Length;\n    return n == 1 || n == 4;\n}","tryCatchPattern":"try { var (l,t,r,b) = ParseMargin(value); }\ncatch (ArgumentException ex) when (ex.Message.Contains(\"Invalid 'margin'\"))\n{\n    // fall back to a single uniform margin, or surface a user error\n}","preventionTips":["Use a single length for uniform margins or exactly four comma-separated L,T,R,B values.","Do not use CSS space shorthand or TRBL order.","Remove trailing/leading commas and empty fields.","Pre-validate the part count is 1 or 4 before calling."],"tags":["excel","drawing","shape","margin","length","validation"],"backgroundTag":null,"analyzedSha":"1ced45e900782c5083ed550ddf328ee974e425e7","analyzedAt":"2026-08-13T13:01:07.193Z","schemaVersion":2},"datasetVersion":"2026-08-13T14:17:21.547Z"}