{"record":{"id":"28ece2d94fc7873d","repo":"iOfficeAI/OfficeCLI","slug":"invalid-labelpos-value-for-pie-chart-st-dlblp","errorCode":null,"errorMessage":"Invalid labelPos '{value}' for pie chart: ST_DLblPosPie allows only bestFit, ctr, inEnd, inBase.","messagePattern":"Invalid labelPos '(.+?)' for pie chart: ST_DLblPosPie allows only bestFit, ctr, inEnd, inBase\\.","errorType":"validation","errorClass":"ArgumentException","httpStatus":null,"severity":"error","filePath":"src/officecli/Core/Chart/ChartHelper.Setter.cs","lineNumber":674,"sourceCode":"                        || plotArea2.Elements<C.Line3DChart>().Any(c =>\n                            IsStackedLineGrouping(c.GetFirstChild<C.Grouping>()?.Val));\n                        // AreaChart/Area3DChart are not checked here: the\n                        // dLblPos handler early-exits for area charts above\n                        // (line 256-259), so any area-stacked check below\n                        // would be unreachable dead code.\n\n                    // OOXML ST_DLblPosPie restricts pie/pie3D to {bestFit, ctr, inEnd, inBase}.\n                    // outEnd/t/b/l/r are not legal here — reject up front instead of\n                    // silently remapping to BestFit and reporting \"Updated labelPos=...\".\n                    if (isPie)\n                    {\n                        var lc = value.ToLowerInvariant();\n                        var pieAllowed = lc is \"bestfit\" or \"best\" or \"auto\"\n                            or \"center\" or \"ctr\"\n                            or \"insideend\" or \"inend\" or \"inside\"\n                            or \"insidebase\" or \"inbase\" or \"base\";\n                        if (!pieAllowed)\n                            throw new ArgumentException(\n                                $\"Invalid labelPos '{value}' for pie chart: ST_DLblPosPie allows only bestFit, ctr, inEnd, inBase.\");\n                    }\n                    var dlblPos = value.ToLowerInvariant() switch\n                    {\n                        \"center\" or \"ctr\" => C.DataLabelPositionValues.Center,\n                        \"insideend\" or \"inend\" or \"inside\" => C.DataLabelPositionValues.InsideEnd,\n                        \"insidebase\" or \"inbase\" or \"base\" => C.DataLabelPositionValues.InsideBase,\n                        \"outsideend\" or \"outend\" or \"outside\" => isStacked\n                            ? C.DataLabelPositionValues.InsideEnd\n                            : C.DataLabelPositionValues.OutsideEnd,\n                        \"bestfit\" or \"best\" or \"auto\" => isStacked\n                            ? C.DataLabelPositionValues.Center\n                            : C.DataLabelPositionValues.BestFit,\n                        \"top\" or \"t\" => isStacked\n                            ? C.DataLabelPositionValues.InsideEnd\n                            : C.DataLabelPositionValues.Top,\n                        \"bottom\" or \"b\" => isStacked\n                            ? C.DataLabelPositionValues.InsideBase","sourceCodeStart":656,"sourceCodeEnd":692,"githubUrl":"https://github.com/iOfficeAI/OfficeCLI/blob/1ced45e900782c5083ed550ddf328ee974e425e7/src/officecli/Core/Chart/ChartHelper.Setter.cs#L656-L692","documentation":"Thrown when setting 'labelPos' on a pie or pie3D chart to a value outside the OOXML ST_DLblPosPie facet, which only permits bestFit, ctr, inEnd, inBase. Bar/line/scatter positions like outEnd, t, b, l, r are illegal on pie charts; Excel refuses such a file. The setter checks isPie up front and rejects rather than silently remapping to BestFit.","triggerScenarios":"SetChartProperties on a C.PieChart or C.Pie3DChart with { [\"labelPos\"] = \"outEnd\" } (or 'outside', 't', 'top', 'b', 'bottom', 'l', 'left', 'r', 'right'). The accepted pie aliases are bestfit/best/auto, center/ctr, insideend/inend/inside, insidebase/inbase/base.","commonSituations":"Reusing a labelPos config block built for a bar chart on a pie chart; generic 'outside' label preference applied to a dashboard containing pie charts; dump→replay of a mixed chart type where the position does not cross-map.","solutions":["For pie charts use only bestFit, ctr, inEnd, or inBase (or their aliases).","Branch labelPos by chart type in your config so bar-style positions are not sent to pie charts.","If you need outside labels, switch the chart type away from pie — pie geometry has no legal 'outside' slot."],"exampleFix":"// before\nSetChartProperties(part, new() { [\"labelPos\"] = \"outEnd\" }); // on a pie chart\n// after\nvar pos = isPie ? \"bestFit\" : \"outEnd\";\nSetChartProperties(part, new() { [\"labelPos\"] = pos });","handlingStrategy":"validation","validationCode":"static readonly HashSet<string> PieLabelPos =\n    new[]{\"bestfit\",\"best\",\"auto\",\"center\",\"ctr\",\"insideend\",\"inend\",\"inside\",\n          \"insidebase\",\"inbase\",\"base\"}, StringComparer.OrdinalIgnoreCase);\n\nstatic bool IsValidPieLabelPos(string v) =>\n    !string.IsNullOrWhiteSpace(v) && PieLabelPos.Contains(v.Trim().ToLowerInvariant());","typeGuard":"static bool IsLegalPieLabelPos(string v) =>\n    (v?.Trim().ToLowerInvariant()) switch\n    {\n        \"bestfit\" or \"best\" or \"auto\" or \"center\" or \"ctr\"\n        or \"insideend\" or \"inend\" or \"inside\"\n        or \"insidebase\" or \"inbase\" or \"base\" => true,\n        _ => false\n    };","tryCatchPattern":"try { SetChartProperties(part, props); }\ncatch (ArgumentException ex) when (ex.Message.Contains(\"ST_DLblPosPie\"))\n{ /* branch labelPos by chart type and retry */ }","preventionTips":["Branch labelPos by chart type in your config layer; never reuse bar positions on pie charts.","For pie charts default to bestFit when the requested position is illegal.","Whitelist labelPos per chart family before calling Set."],"tags":["ooxml","chart","input-validation","pie-chart","data-labels","csharp"],"backgroundTag":null,"analyzedSha":"1ced45e900782c5083ed550ddf328ee974e425e7","analyzedAt":"2026-08-13T13:01:07.193Z","schemaVersion":2},"datasetVersion":"2026-08-13T14:17:21.547Z"}