iOfficeAI/OfficeCLI · error · ArgumentException

trendline.period must be >= 2 (OOXML ST_Skip MinInclusive=2)

Error message

trendline.period must be >= 2 (OOXML ST_Skip MinInclusive=2). Got: {periodVal}.

What it means

Thrown by ApplyTrendlineOptions (ChartHelper.SetterHelpers.cs:183) when the dotted key trendline.period (or the period slot of a BuildTrendline spec via the separate code path) receives an integer below 2. Same OOXML ST_Skip MinInclusive=2 constraint as error 184; this is the post-build per-property setter path rather than the build-spec path. The pre-fix code clamped silently, hiding invalid input from callers, so it now throws.

Source

Thrown at src/officecli/Core/Chart/ChartHelper.SetterHelpers.cs:183

            case "forward" or "forecastforward":
                trendline.RemoveAllChildren<C.Forward>();
                trendline.AppendChild(new C.Forward { Val = ParseHelpers.SafeParseDouble(value, "trendline.forward") });
                break;
            case "backward" or "forecastbackward":
                trendline.RemoveAllChildren<C.Backward>();
                trendline.AppendChild(new C.Backward { Val = ParseHelpers.SafeParseDouble(value, "trendline.backward") });
                break;
            case "order":
                trendline.RemoveAllChildren<C.PolynomialOrder>();
                trendline.AppendChild(new C.PolynomialOrder { Val = (byte)Math.Clamp(ParseHelpers.SafeParseInt(value, "trendline.order"), 2, 6) });
                break;
            case "period":
            {
                // OOXML ST_Skip MinInclusive=2. Pre-fix code clamped < 2 to 2;
                // silently coerce hid invalid input from callers. Throw instead.
                var periodVal = ParseHelpers.SafeParseInt(value, "trendline.period");
                if (periodVal < 2)
                    throw new ArgumentException($"trendline.period must be >= 2 (OOXML ST_Skip MinInclusive=2). Got: {periodVal}.");
                trendline.RemoveAllChildren<C.Period>();
                trendline.AppendChild(new C.Period { Val = (uint)periodVal });
                break;
            }
            case "intercept":
                trendline.RemoveAllChildren<C.Intercept>();
                trendline.AppendChild(new C.Intercept { Val = ParseHelpers.SafeParseDouble(value, "trendline.intercept") });
                break;
            case "disprsqr" or "rsquared" or "r2" or "displayrsquared":
            {
                // CT_Trendline schema order (per ECMA-376 §21.2.2.211):
                //   ... intercept → dispRSqr → dispEq → trendlineLbl → extLst
                // dispRSqr comes BEFORE dispEq. Anchor on the first later-
                // schema sibling so both Set orders produce valid XML.
                trendline.RemoveAllChildren<C.DisplayRSquaredValue>();
                var newRsqr = new C.DisplayRSquaredValue { Val = ParseHelpers.IsTruthy(value) };
                var rsqrAnchor = (OpenXmlElement?)trendline.GetFirstChild<C.DisplayEquation>()
                    ?? trendline.GetFirstChild<C.TrendlineLabel>();

View on GitHub (pinned to 1ced45e900)

Solutions

  1. Set trendline.period to an integer >= 2.
  2. Only set period on moving-average trendlines — it is not meaningful for other types.

Example fix

// before
series1.trendline.period=1
// after
series1.trendline.period=3
Defensive patterns

Strategy: validation

Validate before calling

static int ResolveTrendlinePeriod(string value)
{
    var p = ParseHelpers.SafeParseInt(value, "trendline.period");
    return p >= 2 ? p : throw new ArgumentException("trendline.period must be >= 2");
}

Type guard

static bool IsValidTrendlinePeriod(string value) =>
    int.TryParse(value, out var p) && p >= 2;

Try / catch

try { /* set series1.trendline.period=N */ }
catch (ArgumentException ex) when (ex.Message.Contains("trendline.period must be >= 2"))
{ /* prompt for a value >= 2 */ }

Prevention

When it happens

Trigger: Setting series1.trendline.period=0, series1.trendline.period=1, or chart-level trendline.period=1 on a moving-average trendline.

Common situations: Driving period from a variable that defaults to 0/1; setting period generically across trendline types without knowing moving-average's floor; replaying a dumped period that was edited down.

Related errors


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