{"record":{"id":"4fa638db803672da","repo":"iOfficeAI/OfficeCLI","slug":"trendline-period-must-be-2-ooxml-st-skip-minin","errorCode":null,"errorMessage":"trendline.period must be >= 2 (OOXML ST_Skip MinInclusive=2). Got: {periodVal}.","messagePattern":"trendline\\.period must be >= 2 \\(OOXML ST_Skip MinInclusive=2\\)\\. Got: (.+?)\\.","errorType":"validation","errorClass":"ArgumentException","httpStatus":null,"severity":"error","filePath":"src/officecli/Core/Chart/ChartHelper.SetterHelpers.cs","lineNumber":183,"sourceCode":"            case \"forward\" or \"forecastforward\":\n                trendline.RemoveAllChildren<C.Forward>();\n                trendline.AppendChild(new C.Forward { Val = ParseHelpers.SafeParseDouble(value, \"trendline.forward\") });\n                break;\n            case \"backward\" or \"forecastbackward\":\n                trendline.RemoveAllChildren<C.Backward>();\n                trendline.AppendChild(new C.Backward { Val = ParseHelpers.SafeParseDouble(value, \"trendline.backward\") });\n                break;\n            case \"order\":\n                trendline.RemoveAllChildren<C.PolynomialOrder>();\n                trendline.AppendChild(new C.PolynomialOrder { Val = (byte)Math.Clamp(ParseHelpers.SafeParseInt(value, \"trendline.order\"), 2, 6) });\n                break;\n            case \"period\":\n            {\n                // OOXML ST_Skip MinInclusive=2. Pre-fix code clamped < 2 to 2;\n                // silently coerce hid invalid input from callers. Throw instead.\n                var periodVal = ParseHelpers.SafeParseInt(value, \"trendline.period\");\n                if (periodVal < 2)\n                    throw new ArgumentException($\"trendline.period must be >= 2 (OOXML ST_Skip MinInclusive=2). Got: {periodVal}.\");\n                trendline.RemoveAllChildren<C.Period>();\n                trendline.AppendChild(new C.Period { Val = (uint)periodVal });\n                break;\n            }\n            case \"intercept\":\n                trendline.RemoveAllChildren<C.Intercept>();\n                trendline.AppendChild(new C.Intercept { Val = ParseHelpers.SafeParseDouble(value, \"trendline.intercept\") });\n                break;\n            case \"disprsqr\" or \"rsquared\" or \"r2\" or \"displayrsquared\":\n            {\n                // CT_Trendline schema order (per ECMA-376 §21.2.2.211):\n                //   ... intercept → dispRSqr → dispEq → trendlineLbl → extLst\n                // dispRSqr comes BEFORE dispEq. Anchor on the first later-\n                // schema sibling so both Set orders produce valid XML.\n                trendline.RemoveAllChildren<C.DisplayRSquaredValue>();\n                var newRsqr = new C.DisplayRSquaredValue { Val = ParseHelpers.IsTruthy(value) };\n                var rsqrAnchor = (OpenXmlElement?)trendline.GetFirstChild<C.DisplayEquation>()\n                    ?? trendline.GetFirstChild<C.TrendlineLabel>();","sourceCodeStart":165,"sourceCodeEnd":201,"githubUrl":"https://github.com/iOfficeAI/OfficeCLI/blob/1ced45e900782c5083ed550ddf328ee974e425e7/src/officecli/Core/Chart/ChartHelper.SetterHelpers.cs#L165-L201","documentation":"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.","triggerScenarios":"Setting series1.trendline.period=0, series1.trendline.period=1, or chart-level trendline.period=1 on a moving-average trendline.","commonSituations":"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.","solutions":["Set trendline.period to an integer >= 2.","Only set period on moving-average trendlines — it is not meaningful for other types."],"exampleFix":"// before\nseries1.trendline.period=1\n// after\nseries1.trendline.period=3","handlingStrategy":"validation","validationCode":"static int ResolveTrendlinePeriod(string value)\n{\n    var p = ParseHelpers.SafeParseInt(value, \"trendline.period\");\n    return p >= 2 ? p : throw new ArgumentException(\"trendline.period must be >= 2\");\n}","typeGuard":"static bool IsValidTrendlinePeriod(string value) =>\n    int.TryParse(value, out var p) && p >= 2;","tryCatchPattern":"try { /* set series1.trendline.period=N */ }\ncatch (ArgumentException ex) when (ex.Message.Contains(\"trendline.period must be >= 2\"))\n{ /* prompt for a value >= 2 */ }","preventionTips":["Only set trendline.period on moving-average trendlines.","Clamp UI input to a minimum of 2 before sending.","Treat 0/1 as 'use default (2)' rather than forwarding the raw value."],"tags":["chart","trendline","moving-average","validation","ooxml"],"backgroundTag":null,"analyzedSha":"1ced45e900782c5083ed550ddf328ee974e425e7","analyzedAt":"2026-08-13T13:01:07.193Z","schemaVersion":2},"datasetVersion":"2026-08-13T14:17:21.547Z"}