{"record":{"id":"5a095196807b5ff8","repo":"iOfficeAI/OfficeCLI","slug":"invalid-legend-position-posspec-valid-none","errorCode":null,"errorMessage":"Invalid legend position '{posSpec}'. Valid: none, top, bottom, left, right, topRight (or use 'none'/'false' to hide the legend).","messagePattern":"Invalid legend position '(.+?)'\\. Valid: none, top, bottom, left, right, topRight \\(or use 'none'/'false' to hide the legend\\)\\.","errorType":"validation","errorClass":"ArgumentException","httpStatus":null,"severity":"error","filePath":"src/officecli/Core/Chart/ChartExBuilder.cs","lineNumber":466,"sourceCode":"        {\n            Align = CX.PosAlign.Ctr,\n            Overlay = false,\n        };\n        // CONSISTENCY(strict-enums / R34-1): unknown legend tokens used to\n        // silently fall through to right; mirror cChart's strict validation.\n        // Note: cx:legend's SidePos has no topRight — fall back to top with\n        // a clear note rather than rejecting, since topRight is a valid\n        // value for the regular cChart variant and users may pass it through.\n        // CONSISTENCY(legend-separator-normalize): mirror SetterHelpers — dash\n        // and underscore separators are equivalent (top-right == top_right).\n        var posSpecNorm = SchemaKeyNormalizer.Normalize(posSpec);\n        legend.Pos = posSpecNorm switch\n        {\n            \"top\" or \"t\" or \"topright\" or \"tr\" => CX.SidePos.T,\n            \"bottom\" or \"b\" => CX.SidePos.B,\n            \"left\" or \"l\"   => CX.SidePos.L,\n            \"right\" or \"r\"  => CX.SidePos.R,\n            _ => throw new ArgumentException(\n                $\"Invalid legend position '{posSpec}'. \" +\n                \"Valid: none, top, bottom, left, right, topRight \" +\n                \"(or use 'none'/'false' to hide the legend).\"),\n        };\n\n        if (properties != null)\n        {\n            // Optional overlay flag — matches regular cChart's `legend.overlay`.\n            var overlay = properties.GetValueOrDefault(\"legend.overlay\")\n                       ?? properties.GetValueOrDefault(\"legendoverlay\");\n            if (!string.IsNullOrEmpty(overlay))\n                legend.Overlay = ParseHelpers.IsTruthy(overlay);\n\n            // Compound font styling — \"size:color:fontname\", same form as\n            // regular cChart's `legendfont`. Wraps an a:defRPr in cx:txPr.\n            var legendFont = properties.GetValueOrDefault(\"legendfont\")\n                          ?? properties.GetValueOrDefault(\"legend.font\");\n            if (!string.IsNullOrEmpty(legendFont))","sourceCodeStart":448,"sourceCodeEnd":484,"githubUrl":"https://github.com/iOfficeAI/OfficeCLI/blob/1ced45e900782c5083ed550ddf328ee974e425e7/src/officecli/Core/Chart/ChartExBuilder.cs#L448-L484","documentation":"The chart legend position setter (ChartExBuilder) normalizes the position spec via SchemaKeyNormalizer (dash/underscore equivalents), then maps it to a CX.SidePos enum value. Only top, bottom, left, right, and topRight are accepted (with short aliases t, b, l, r, tr). 'none' and 'false' hide the legend but are handled upstream, not in this switch. Any other value falls to the default arm and throws.","triggerScenarios":"Setting legend position via the chart-ex builder's properties API with an unrecognized string, e.g. legendPos=\"middle\", \"center\", \"diagonal\", or a locale-specific string. The value passes through SchemaKeyNormalizer.Normalize but does not match any switch arm.","commonSituations":"Typing 'center' or 'middle' (not supported by cx:legend SidePos). Using 'bottomRight' or 'topLeft' (only topRight exists for the regular cChart variant, but cx:legend has no topRight — it falls back to top). Passing an abbreviation not in the alias list.","solutions":["Use one of the valid values: none, top, bottom, left, right, topRight (or aliases t, b, l, r, tr).","To hide the legend, pass 'none' or 'false' — these are handled before reaching the position switch.","For 'center', there is no cx:legend equivalent — restructure the chart or omit the legend position."],"exampleFix":"// before\nlegend.Pos = \"center\";\n// after\nlegend.Pos = \"top\"; // or \"bottom\", \"left\", \"right\", \"topRight\"","handlingStrategy":"validation","validationCode":"static readonly HashSet<string> ValidLegendPositions = new(StringComparer.OrdinalIgnoreCase)\n{ \"top\", \"bottom\", \"left\", \"right\", \"topRight\", \"none\", \"false\",\n  \"t\", \"b\", \"l\", \"r\", \"tr\" };\n\nstatic bool IsValidLegendPosition(string pos)\n    => ValidLegendPositions.Contains(pos.Replace('-', '_').ToLowerInvariant());","typeGuard":null,"tryCatchPattern":"try { chartExBuilder.SetLegendPosition(posSpec); }\ncatch (ArgumentException ex) when (ex.Message.StartsWith(\"Invalid legend position\"))\n{\n    Console.Error.WriteLine($\"{ex.Message}\\nFalling back to default legend position.\");\n    chartExBuilder.SetLegendPosition(\"top\");\n}","preventionTips":["Use the canonical values: top, bottom, left, right, topRight.","Use 'none' or 'false' to hide the legend.","Validate against the allowed set before passing user input to the chart builder."],"tags":["chart","legend","chartex","invalid-value"],"backgroundTag":null,"analyzedSha":"1ced45e900782c5083ed550ddf328ee974e425e7","analyzedAt":"2026-08-13T13:01:07.193Z","schemaVersion":2},"datasetVersion":"2026-08-13T14:17:21.547Z"}