{"record":{"id":"a7c98432d4df9cbd","repo":"iOfficeAI/OfficeCLI","slug":"invalid-legend-position-value-valid-none-to","errorCode":null,"errorMessage":"Invalid legend position '{value}'. 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/ChartHelper.SetterHelpers.cs","lineNumber":40,"sourceCode":"    /// \"Updated: legend=hidden\" success message while the file actually\n    /// carried legend=bottom (R34-1). Caller should already have handled\n    /// \"none\" / \"false\" (legend removal) before reaching here.\n    /// </summary>\n    internal static C.LegendPositionValues ParseLegendPosition(string value)\n    {\n        // CONSISTENCY(legend-separator-normalize): accept dash AND underscore\n        // as separators (`top-right`, `top_right`, `TOP_RIGHT`) by stripping\n        // both before comparison. Without this, `TOP_RIGHT` threw while\n        // `top-right` succeeded — punctuation variants should be uniform.\n        var norm = SchemaKeyNormalizer.Normalize(value);\n        return norm switch\n        {\n            \"top\" or \"t\" => C.LegendPositionValues.Top,\n            \"bottom\" or \"b\" => C.LegendPositionValues.Bottom,\n            \"left\" or \"l\" => C.LegendPositionValues.Left,\n            \"right\" or \"r\" => C.LegendPositionValues.Right,\n            \"topright\" or \"tr\" => C.LegendPositionValues.TopRight,\n            _ => throw new ArgumentException(\n                $\"Invalid legend position '{value}'. \" +\n                \"Valid: none, top, bottom, left, right, topRight \" +\n                \"(or use 'none'/'false' to hide the legend).\"),\n        };\n    }\n\n    // ==================== Tick Mark Helpers ====================\n\n    internal static C.TickMarkValues ParseTickMark(string value)\n    {\n        return value.ToLowerInvariant() switch\n        {\n            \"none\" or \"false\" => C.TickMarkValues.None,\n            \"in\" or \"inside\" => C.TickMarkValues.Inside,\n            \"out\" or \"outside\" => C.TickMarkValues.Outside,\n            \"cross\" or \"both\" => C.TickMarkValues.Cross,\n            _ => throw new ArgumentException(\n                $\"Invalid tick mark value '{value}'. Valid values: none, in, out, cross.\")","sourceCodeStart":22,"sourceCodeEnd":58,"githubUrl":"https://github.com/iOfficeAI/OfficeCLI/blob/1ced45e900782c5083ed550ddf328ee974e425e7/src/officecli/Core/Chart/ChartHelper.SetterHelpers.cs#L22-L58","documentation":"Thrown by ParseLegendPosition (ChartHelper.SetterHelpers.cs:40) when the legend position string, after SchemaKeyNormalizer.Normalize (which strips dash/underscore separators and lowercases), does not match top/t, bottom/b, left/l, right/r, or topright/tr. The method is reached only after the caller has already handled 'none'/'false' (legend removal), so any remaining unknown token is a genuine error. It exists because the legacy code silently coerced unknown tokens to 'bottom', producing a contradictory success message while the file carried legend=bottom (R34-1).","triggerScenarios":"Setting legend=<position> to a token that is not top/bottom/left/right/topright or their single-letter aliases, e.g. 'top-left', 'center', 'inside', 'tr' misspelled, 'northeast'.","commonSituations":"Confusing PowerPoint's 'Top Left'/'Bottom Center' UI labels with OOXML's five-position enum; passing a multi-word position like 'top left' that normalize does not collapse; copying 'l' vs 'r' single letters incorrectly.","solutions":["Use one of: top, bottom, left, right, topRight (or aliases t/b/l/r/tr).","To hide the legend, use 'none' or 'false' — those are handled before this parser and never reach it.","If passing a compound like 'top-right', note SchemaKeyNormalizer already strips dashes/underscores, so 'top-right' works but 'top left' (space) does not."],"exampleFix":"// before\nlegend=top-left\n// after\nlegend=topLeft","handlingStrategy":"validation","validationCode":"static readonly Dictionary<string,string> LegendPositions = new(StringComparer.OrdinalIgnoreCase)\n{ [\"top\"]=\"top\",[\"t\"]=\"top\",[\"bottom\"]=\"bottom\",[\"b\"]=\"bottom\",[\"left\"]=\"left\",[\"l\"]=\"left\",[\"right\"]=\"right\",[\"r\"]=\"right\",[\"topright\"]=\"topRight\",[\"tr\"]=\"topRight\" };\nstatic string ResolveLegendPosition(string v) => LegendPositions.TryGetValue(v ?? \"\", out var p) ? p : throw new ArgumentException($\"invalid legend position '{v}'\");","typeGuard":"static bool IsValidLegendPosition(string v) => LegendPositions.ContainsKey(v ?? \"\");","tryCatchPattern":"try { /* set chart legend=... */ }\ncatch (ArgumentException ex) when (ex.Message.Contains(\"Invalid legend position\"))\n{ /* prompt user with the 5 valid positions */ }","preventionTips":["Handle 'none'/'false' (legend removal) before calling the position parser.","Strip dashes/underscores client-side to match SchemaKeyNormalizer behaviour.","Avoid multi-word positions with spaces — use camelCase (topRight) or dash (top-right)."],"tags":["chart","legend","validation"],"backgroundTag":null,"analyzedSha":"1ced45e900782c5083ed550ddf328ee974e425e7","analyzedAt":"2026-08-13T13:01:07.193Z","schemaVersion":2},"datasetVersion":"2026-08-13T14:17:21.547Z"}