{"record":{"id":"9783a971a4faf26b","repo":"iOfficeAI/OfficeCLI","slug":"stock-chart-requires-3-or-4-data-series-high-low","errorCode":null,"errorMessage":"stock chart requires 3 or 4 data series (high, low, close [, open]); got {seriesData.Count}.","messagePattern":"stock chart requires 3 or 4 data series \\(high, low, close \\[, open\\]\\); got (.+?)\\.","errorType":"validation","errorClass":"ArgumentException","httpStatus":null,"severity":"error","filePath":"src/officecli/Core/Chart/ChartHelper.Builder.cs","lineNumber":1373,"sourceCode":"        radarChart.AppendChild(new C.AxisId { Val = catAxisId });\n        radarChart.AppendChild(new C.AxisId { Val = valAxisId });\n        return radarChart;\n    }\n\n    // ==================== Stock Chart ====================\n\n    internal static C.StockChart BuildStockChart(\n        string[]? categories, List<(string name, double[] values)> seriesData,\n        uint catAxisId, uint valAxisId)\n    {\n        // Stock chart expects series in Open-High-Low-Close order (4 series)\n        // or High-Low-Close order (3 series)\n        // BUG-R6A(BUG2): OOXML CT_StockChart constrains c:ser to minOccurs=3,\n        // maxOccurs=4. Any other count writes a schema-invalid file (e.g.\n        // c:hiLowLines appears where the validator still expects c:ser). Reject\n        // up front with an actionable message rather than emitting broken XML.\n        if (seriesData.Count is < 3 or > 4)\n            throw new ArgumentException(\n                $\"stock chart requires 3 or 4 data series (high, low, close [, open]); got {seriesData.Count}.\");\n\n        var stockChart = new C.StockChart();\n\n        for (int i = 0; i < seriesData.Count; i++)\n        {\n            var series = new C.LineChartSeries(\n                new C.Index { Val = (uint)i },\n                new C.Order { Val = (uint)i },\n                BuildSeriesText(seriesData[i].name)\n            );\n\n            // Hide individual series lines — stock chart visuals come from\n            // hiLowLines + upDownBars, not from the series lines themselves\n            var spPr = new C.ChartShapeProperties();\n            spPr.AppendChild(new Drawing.Outline(new Drawing.NoFill()));\n            series.AppendChild(spPr);\n","sourceCodeStart":1355,"sourceCodeEnd":1391,"githubUrl":"https://github.com/iOfficeAI/OfficeCLI/blob/1ced45e900782c5083ed550ddf328ee974e425e7/src/officecli/Core/Chart/ChartHelper.Builder.cs#L1355-L1391","documentation":"Stock charts in OOXML (CT_StockChart) require exactly 3 or 4 data series: High-Low-Close (3) or Open-High-Low-Close (4). The minOccurs=3, maxOccurs=4 constraint is schema-enforced; any other count writes a schema-invalid file (e.g. c:hiLowLines appears where the validator still expects c:ser). The library rejects up front rather than emitting broken XML.","triggerScenarios":"Building a stock chart with fewer than 3 series (e.g. just high+low) or more than 4 series (e.g. high+low+close+open+volume). The check fires at the top of BuildStockChart before any series elements are constructed.","commonSituations":"Passing 2 series (high+low) expecting a high-low chart — OOXML requires at least 3. Passing 5 series (adding volume) — exceeds the maxOccurs=4 constraint. Not providing data in the correct OHLC/HLC order. Confusing stock chart requirements with candlestick chart libraries that accept arbitrary series counts.","solutions":["Provide exactly 3 series (High, Low, Close) in that order.","Or provide exactly 4 series (Open, High, Low, Close) in OHLC order.","If you need volume data, use a combo chart (stock+bar) instead of adding a 5th series to the stock chart."],"exampleFix":"// before\nseries: [{ name: \"High\", values: [10, 20, 30] }, { name: \"Low\", values: [5, 10, 15] }]\nkind: \"stock\"\n// after (3 series: HLC)\nseries: [\n  { name: \"High\",  values: [10, 20, 30] },\n  { name: \"Low\",   values: [5, 10, 15] },\n  { name: \"Close\", values: [8, 15, 25] }\n]\nkind: \"stock\"\n// or 4 series: OHLC\nseries: [\n  { name: \"Open\",  values: [7, 12, 18] },\n  { name: \"High\",  values: [10, 20, 30] },\n  { name: \"Low\",   values: [5, 10, 15] },\n  { name: \"Close\", values: [8, 15, 25] }\n]","handlingStrategy":"validation","validationCode":"static bool IsValidStockSeriesCount(int count) => count is >= 3 and <= 4;\n\n// Before building:\nif (kind == \"stock\" && !IsValidStockSeriesCount(seriesData.Count))\n    throw new ArgumentException(\n        $\"Stock chart requires 3 (HLC) or 4 (OHLC) series; got {seriesData.Count}.\");","typeGuard":null,"tryCatchPattern":"try { ChartHelper.BuildStockChart(categories, seriesData, catAxisId, valAxisId); }\ncatch (ArgumentException ex) when (ex.Message.StartsWith(\"stock chart requires\"))\n{\n    Console.Error.WriteLine($\"{ex.Message}\\nProvide 3 series (High, Low, Close) or 4 (Open, High, Low, Close).\");\n}","preventionTips":["Provide exactly 3 series (High, Low, Close) or 4 series (Open, High, Low, Close).","Order matters: HLC or OHLC, not arbitrary order.","For volume data, use a combo chart (stock+bar), not a 5-series stock chart."],"tags":["chart","stock-chart","series-count","ooxml-schema"],"backgroundTag":null,"analyzedSha":"1ced45e900782c5083ed550ddf328ee974e425e7","analyzedAt":"2026-08-13T13:01:07.193Z","schemaVersion":2},"datasetVersion":"2026-08-13T14:17:21.547Z"}