{"record":{"id":"ecdc344400fd1ab2","repo":"iOfficeAI/OfficeCLI","slug":"movingavg-period-must-be-2-ooxml-st-skip-minin","errorCode":null,"errorMessage":"movingAvg period must be >= 2 (OOXML ST_Skip MinInclusive=2). Got: {order}.","messagePattern":"movingAvg 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":100,"sourceCode":"                $\"Invalid trendline type '{parts[0]}'. \" +\n                \"Valid: linear, exp, log, poly, power, movingAvg. \" +\n                \"For per-series different trendlines use seriesN.trendline keys, \" +\n                \"not pipe-separated lists.\")\n                { Code = \"invalid_value\" }\n        };\n        trendline.AppendChild(new C.TrendlineType { Val = trendType });\n\n        // Polynomial order or moving average period\n        if (parts.Length > 1 && int.TryParse(parts[1], out var order))\n        {\n            if (trendType == C.TrendlineValues.Polynomial)\n                trendline.AppendChild(new C.PolynomialOrder { Val = (byte)Math.Clamp(order, 2, 6) });\n            else if (trendType == C.TrendlineValues.MovingAverage)\n            {\n                // OOXML ST_Skip MinInclusive=2 (c:period inside c:trendline).\n                // Pre-fix code silently accepted order=0/1 which Word 422s on.\n                if (order < 2)\n                    throw new ArgumentException($\"movingAvg period must be >= 2 (OOXML ST_Skip MinInclusive=2). Got: {order}.\");\n                trendline.AppendChild(new C.Period { Val = (uint)order });\n            }\n            else\n            {\n                // Treat as forward extrapolation periods\n                trendline.AppendChild(new C.Forward { Val = order });\n            }\n        }\n        // OOXML CT_Trendline requires <c:period> when trendlineType=movingAvg;\n        // Word rejects the file otherwise. When no explicit period was given,\n        // fall back to 2 (Excel's default for \"Add Trendline → Moving Average\").\n        if (trendType == C.TrendlineValues.MovingAverage\n            && trendline.GetFirstChild<C.Period>() == null)\n        {\n            trendline.AppendChild(new C.Period { Val = 2u });\n        }\n        // Same family for polynomial: <c:order> is required for poly trendlines.\n        // Default to degree 2 (Excel's default for \"Add Trendline → Polynomial\").","sourceCodeStart":82,"sourceCodeEnd":118,"githubUrl":"https://github.com/iOfficeAI/OfficeCLI/blob/1ced45e900782c5083ed550ddf328ee974e425e7/src/officecli/Core/Chart/ChartHelper.SetterHelpers.cs#L82-L118","documentation":"Thrown by BuildTrendline (ChartHelper.SetterHelpers.cs:100) when a moving-average trendline spec (movingAvg:N) carries a period value less than 2. OOXML's ST_Skip type (the c:period element inside c:trendline) has MinInclusive=2, and Word returns error 422 on files that violate it. The pre-fix code silently accepted 0/1, producing corrupt files. When no explicit period is given the code defaults to 2 (Excel's default), so this only fires on an explicit bad value.","triggerScenarios":"Setting series1.trendline=movingAvg:0 or movingAvg:1, or passing 'moving:1' / 'movingAverage:0'.","commonSituations":"Assuming a moving-average period of 1 means 'every point'; passing 0 to mean 'default'; reusing a generic 'order' parameter value across polynomial and moving-average specs without adjusting the minimum.","solutions":["Set the moving-average period to 2 or higher, e.g. movingAvg:2.","Omit the period entirely to get the Excel default of 2."],"exampleFix":"// before\nseries1.trendline=movingAvg:1\n// after\nseries1.trendline=movingAvg:3","handlingStrategy":"validation","validationCode":"static int ResolveMovingAvgPeriod(string spec)\n{\n    var parts = spec.Split(':');\n    if (parts.Length < 2) return 2; // default\n    if (!int.TryParse(parts[1], out var p) || p < 2) throw new ArgumentException(\"movingAvg period must be >= 2\");\n    return p;\n}","typeGuard":"static bool IsValidMovingAvgPeriod(string spec)\n{\n    var parts = spec.Split(':');\n    return parts.Length < 2 || (int.TryParse(parts[1], out var p) && p >= 2);\n}","tryCatchPattern":"try { /* set series1.trendline=movingAvg:N */ }\ncatch (ArgumentException ex) when (ex.Message.Contains(\"movingAvg period must be >= 2\"))\n{ /* coerce N to 2 or prompt user */ }","preventionTips":["Default the moving-average period to 2 (Excel's default) when unsure.","Do not reuse a generic 'order' variable for moving-average period without checking the floor.","Remember polynomial order is clamped to [2,6] but moving-average period must be >= 2 and is not clamped."],"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"}