iOfficeAI/OfficeCLI · error · ArgumentException

Invalid labelPos '{value}' for pie chart: ST_DLblPosPie allo

Error message

Invalid labelPos '{value}' for pie chart: ST_DLblPosPie allows only bestFit, ctr, inEnd, inBase.

What it means

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.

Source

Thrown at src/officecli/Core/Chart/ChartHelper.Setter.cs:674

                        || plotArea2.Elements<C.Line3DChart>().Any(c =>
                            IsStackedLineGrouping(c.GetFirstChild<C.Grouping>()?.Val));
                        // AreaChart/Area3DChart are not checked here: the
                        // dLblPos handler early-exits for area charts above
                        // (line 256-259), so any area-stacked check below
                        // would be unreachable dead code.

                    // OOXML ST_DLblPosPie restricts pie/pie3D to {bestFit, ctr, inEnd, inBase}.
                    // outEnd/t/b/l/r are not legal here — reject up front instead of
                    // silently remapping to BestFit and reporting "Updated labelPos=...".
                    if (isPie)
                    {
                        var lc = value.ToLowerInvariant();
                        var pieAllowed = lc is "bestfit" or "best" or "auto"
                            or "center" or "ctr"
                            or "insideend" or "inend" or "inside"
                            or "insidebase" or "inbase" or "base";
                        if (!pieAllowed)
                            throw new ArgumentException(
                                $"Invalid labelPos '{value}' for pie chart: ST_DLblPosPie allows only bestFit, ctr, inEnd, inBase.");
                    }
                    var dlblPos = value.ToLowerInvariant() switch
                    {
                        "center" or "ctr" => C.DataLabelPositionValues.Center,
                        "insideend" or "inend" or "inside" => C.DataLabelPositionValues.InsideEnd,
                        "insidebase" or "inbase" or "base" => C.DataLabelPositionValues.InsideBase,
                        "outsideend" or "outend" or "outside" => isStacked
                            ? C.DataLabelPositionValues.InsideEnd
                            : C.DataLabelPositionValues.OutsideEnd,
                        "bestfit" or "best" or "auto" => isStacked
                            ? C.DataLabelPositionValues.Center
                            : C.DataLabelPositionValues.BestFit,
                        "top" or "t" => isStacked
                            ? C.DataLabelPositionValues.InsideEnd
                            : C.DataLabelPositionValues.Top,
                        "bottom" or "b" => isStacked
                            ? C.DataLabelPositionValues.InsideBase

View on GitHub (pinned to 1ced45e900)

Solutions

  1. For pie charts use only bestFit, ctr, inEnd, or inBase (or their aliases).
  2. Branch labelPos by chart type in your config so bar-style positions are not sent to pie charts.
  3. If you need outside labels, switch the chart type away from pie — pie geometry has no legal 'outside' slot.

Example fix

// before
SetChartProperties(part, new() { ["labelPos"] = "outEnd" }); // on a pie chart
// after
var pos = isPie ? "bestFit" : "outEnd";
SetChartProperties(part, new() { ["labelPos"] = pos });
Defensive patterns

Strategy: validation

Validate before calling

static readonly HashSet<string> PieLabelPos =
    new[]{"bestfit","best","auto","center","ctr","insideend","inend","inside",
          "insidebase","inbase","base"}, StringComparer.OrdinalIgnoreCase);

static bool IsValidPieLabelPos(string v) =>
    !string.IsNullOrWhiteSpace(v) && PieLabelPos.Contains(v.Trim().ToLowerInvariant());

Type guard

static bool IsLegalPieLabelPos(string v) =>
    (v?.Trim().ToLowerInvariant()) switch
    {
        "bestfit" or "best" or "auto" or "center" or "ctr"
        or "insideend" or "inend" or "inside"
        or "insidebase" or "inbase" or "base" => true,
        _ => false
    };

Try / catch

try { SetChartProperties(part, props); }
catch (ArgumentException ex) when (ex.Message.Contains("ST_DLblPosPie"))
{ /* branch labelPos by chart type and retry */ }

Prevention

When it happens

Trigger: 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.

Common situations: 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.

Related errors


AI-assisted analysis of iOfficeAI/OfficeCLI@1ced45e900 (2026-08-13). Data as JSON: /api/errors/28ece2d94fc7873d. Report an issue: GitHub.