{"record":{"id":"4bd8f4e1454a72bb","repo":"iOfficeAI/OfficeCLI","slug":"unknown-label-position-value-valid-center-i","errorCode":null,"errorMessage":"Unknown label position '{value}'. Valid: center, insideEnd, outsideEnd, insideBase, top, bottom, left, right, bestFit.","messagePattern":"Unknown label position '(.+?)'\\. Valid: center, insideEnd, outsideEnd, insideBase, top, bottom, left, right, bestFit\\.","errorType":"validation","errorClass":"ArgumentException","httpStatus":null,"severity":"error","filePath":"src/officecli/Core/Chart/ChartHelper.SetterHelpers.cs","lineNumber":257,"sourceCode":"    // friendly alias plus the raw schema tokens the Reader emits verbatim\n    // (ctr, t, b, l, r, outEnd, inEnd, inBase, bestFit) so dump→batch replay\n    // always parses. Unknown tokens throw instead of silently coercing to\n    // OutsideEnd (silent-accept enum-miss family); the three former inline\n    // switches each covered a different subset, so a token accepted on one\n    // path could throw or coerce on another.\n    internal static C.DataLabelPositionValues ParseDataLabelPosition(string value) =>\n        value.ToLowerInvariant() switch\n        {\n            \"center\" or \"ctr\" => C.DataLabelPositionValues.Center,\n            \"insideend\" or \"inside\" or \"inend\" => C.DataLabelPositionValues.InsideEnd,\n            \"outsideend\" or \"outside\" or \"outend\" => C.DataLabelPositionValues.OutsideEnd,\n            \"insidebase\" or \"inbase\" or \"base\" => C.DataLabelPositionValues.InsideBase,\n            \"top\" or \"t\" => C.DataLabelPositionValues.Top,\n            \"bottom\" or \"b\" => C.DataLabelPositionValues.Bottom,\n            \"left\" or \"l\" => C.DataLabelPositionValues.Left,\n            \"right\" or \"r\" => C.DataLabelPositionValues.Right,\n            \"bestfit\" or \"best\" => C.DataLabelPositionValues.BestFit,\n            _ => throw new ArgumentException(\n                $\"Unknown label position '{value}'. Valid: center, insideEnd, outsideEnd, insideBase, top, bottom, left, right, bestFit.\")\n        };\n\n    internal static C.ErrorBars BuildErrorBars(string spec)\n    {\n        // Format: \"type\" or \"type:value\" e.g. \"fixed:5\", \"percent:10\", \"stddev\", \"stderr\"\n        // R55 bt-6: cust spec is \"cust:<direction>:<plusCSV>:<minusCSV>\" — emit\n        // per-direction <c:plus>/<c:minus> NumberLiteral arrays. The Reader\n        // pairs with this form (ReadErrorBarSideCsv) so dump-replay of cust\n        // error bars round-trips through the inline numLit cache, not numRef\n        // (which would need a live cell reference on the embedded workbook).\n        // CONSISTENCY(errorbars-bare-number): bare number (e.g. \"5\") is taken as\n        // fixed:<N>, mirroring how other chart numeric specs accept a value-only\n        // shorthand. Without this, \"5\" matched no type-name arm and fell through\n        // to FixedValue with no magnitude — producing zero-height error bars.\n        var parts = spec.Split(':');\n        var typeStr = parts[0].Trim().ToLowerInvariant();\n        string? bareValue = null;","sourceCodeStart":239,"sourceCodeEnd":275,"githubUrl":"https://github.com/iOfficeAI/OfficeCLI/blob/1ced45e900782c5083ed550ddf328ee974e425e7/src/officecli/Core/Chart/ChartHelper.SetterHelpers.cs#L239-L275","documentation":"Thrown by ParseDataLabelPosition (ChartHelper.SetterHelpers.cs:257) when a data-label position token, after ToLowerInvariant, matches none of center/ctr, insideend/inside/inend, outsideend/outside/outend, insidebase/inbase/base, top/t, bottom/b, left/l, right/r, bestfit/best. This is the single source of truth for labelPos alias parsing, covering both friendly aliases and raw schema tokens the Reader emits verbatim so dump-to-replay always works. Unknown tokens throw rather than silently coerce to OutsideEnd (the old silent-accept enum-miss family).","triggerScenarios":"Setting labelPos / dataLabelPosition to an unrecognized token, e.g. 'outside-base', 'auto', 'middle', 'above', 'centered', or a chart-type-specific position that does not exist in the OOXML enum.","commonSituations":"Using a position valid for one chart type on another (e.g. 'bestFit' is pie-only); guessing 'above'/'below' instead of top/bottom; copying an Excel-internal enum name that is not aliased here.","solutions":["Use one of: center, insideEnd, outsideEnd, insideBase, top, bottom, left, right, bestFit (aliases: ctr, inside, inEnd, outside, outEnd, inBase, base, t, b, l, r, best).","Check that the position is valid for the chart type — bestFit is pie/doughnut only, insideBase is bar/column only."],"exampleFix":"// before\nlabelPos=above\n// after\nlabelPos=top","handlingStrategy":"validation","validationCode":"static readonly HashSet<string> LabelPositions = new(StringComparer.OrdinalIgnoreCase)\n{ \"center\",\"ctr\",\"insideend\",\"inside\",\"inend\",\"outsideend\",\"outside\",\"outend\",\"insidebase\",\"inbase\",\"base\",\"top\",\"t\",\"bottom\",\"b\",\"left\",\"l\",\"right\",\"r\",\"bestfit\",\"best\" };\nstatic string ValidateLabelPosition(string v) => LabelPositions.Contains((v ?? \"\").Trim().ToLowerInvariant()) ? v : throw new ArgumentException($\"unknown label position '{v}'\");","typeGuard":"static bool IsValidLabelPosition(string v) => LabelPositions.Contains((v ?? \"\").Trim().ToLowerInvariant());","tryCatchPattern":"try { /* set chart labelPos=... */ }\ncatch (ArgumentException ex) when (ex.Message.Contains(\"Unknown label position\"))\n{ /* list valid positions for the chart type */ }","preventionTips":["Filter positions by chart type: bestFit is pie/doughnut only, insideBase is bar/column only.","Use the schema tokens (outEnd, inEnd, inBase, bestFit) for dump-replay safety.","Avoid inventing positions like 'above'/'middle' — map to top/center."],"tags":["chart","data-labels","validation"],"backgroundTag":null,"analyzedSha":"1ced45e900782c5083ed550ddf328ee974e425e7","analyzedAt":"2026-08-13T13:01:07.193Z","schemaVersion":2},"datasetVersion":"2026-08-13T14:17:21.547Z"}