{"record":{"id":"4d4dcd76be4b1ee7","repo":"iOfficeAI/OfficeCLI","slug":"invalid-secondaryaxis-value-value-valid-fo","errorCode":null,"errorMessage":"Invalid 'secondaryAxis' value: '{value}'. Valid forms: index ('2'), comma index list ('2,3'), 'true', 'false'/'none', seriesN alias ('series2'), or a chart-type name on a combo chart ('line').","messagePattern":"Invalid 'secondaryAxis' value: '(.+?)'\\. Valid forms: index \\('2'\\), comma index list \\('2,3'\\), 'true', 'false'/'none', seriesN alias \\('series2'\\), or a chart-type name on a combo chart \\('line'\\)\\.","errorType":"validation","errorClass":"ArgumentException","httpStatus":null,"severity":"error","filePath":"src/officecli/Core/Chart/ChartHelper.Setter.cs","lineNumber":1725,"sourceCode":"                                var trimmed = s.Trim();\n                                if (int.TryParse(trimmed, out var v)) return v;\n                                var m = System.Text.RegularExpressions.Regex.Match(\n                                    trimmed, @\"^series(\\d+)$\",\n                                    System.Text.RegularExpressions.RegexOptions.IgnoreCase);\n                                return m.Success && int.TryParse(m.Groups[1].Value, out var sv) ? sv : -1;\n                            })\n                            .Where(v => v > 0).ToHashSet();\n                        // Type-name form, e.g. \"line\" on a combo chart — route every\n                        // series whose parent CT_*Chart element matches that type to\n                        // the secondary axis. Without this, \"line\" parsed to an empty\n                        // index set and silently no-op'd, leaving the lineChart bound\n                        // to the primary axId (the R26 combo bug).\n                        if (secondaryIndices.Count == 0)\n                            secondaryIndices = SeriesIndicesForChartType(plotArea2, value);\n                        // R47: still empty → value was not a valid index, type name,\n                        // or seriesN alias. Throw instead of silent no-op.\n                        if (secondaryIndices.Count == 0)\n                            throw new ArgumentException(\n                                $\"Invalid 'secondaryAxis' value: '{value}'. Valid forms: \" +\n                                \"index ('2'), comma index list ('2,3'), 'true', 'false'/'none', \" +\n                                \"seriesN alias ('series2'), or a chart-type name on a combo chart ('line').\");\n                    }\n                    ApplySecondaryAxis(plotArea2, secondaryIndices);\n                    break;\n                }\n\n                case \"plotarea.x\" or \"plotarea.y\" or \"plotarea.w\" or \"plotarea.h\":\n                {\n                    if (!double.TryParse(value, System.Globalization.NumberStyles.Float,\n                        System.Globalization.CultureInfo.InvariantCulture, out var layoutVal)\n                        || !double.IsFinite(layoutVal))\n                    { unsupported.Add(key); break; }\n                    var plotArea3 = chart.GetFirstChild<C.PlotArea>();\n                    if (plotArea3 == null) { unsupported.Add(key); break; }\n                    SetManualLayoutProperty(plotArea3, key.Split('.')[1].ToLowerInvariant(), layoutVal, isPlotArea: true);\n                    break;","sourceCodeStart":1707,"sourceCodeEnd":1743,"githubUrl":"https://github.com/iOfficeAI/OfficeCLI/blob/1ced45e900782c5083ed550ddf328ee974e425e7/src/officecli/Core/Chart/ChartHelper.Setter.cs#L1707-L1743","documentation":"Thrown when 'secondaryAxis' does not match any accepted form after all parses fail: it is not 'true', not 'false'/'none'/blank, not a comma list of positive integer indices, not a 'seriesN' alias list, and not a chart-type name present on a combo chart (SeriesIndicesForChartType returned empty). This is the R47 guard that replaced the old silent no-op behavior.","triggerScenarios":"SetChartProperties with { [\"secondaryAxis\"] = \"all\" }, \"second\", \"0\" (zero is filtered out), or a type name like 'area' on a chart that has no area series.","commonSituations":"Free-text 'secondary' from a UI; zero-based index sent as 0 (indices are 1-based, 0 is dropped); type-name form used on a single-type (non-combo) chart where no series matches.","solutions":["Use a 1-based index or comma list ('2', '2,3'), 'series2' alias, 'true', 'false'/'none', or a chart-type name that exists on the combo chart.","For zero-based UIs, convert: send (uiIndex + 1).","Verify the type-name against the chart's actual CT_*Chart elements before sending."],"exampleFix":"// before\nSetChartProperties(part, new() { [\"secondaryAxis\"] = \"0\" });\n// after\nSetChartProperties(part, new() { [\"secondaryAxis\"] = (uiIndex + 1).ToString() });","handlingStrategy":"validation","validationCode":"static readonly Regex SeriesAlias = new(@\"^series(\\d+)$\", RegexOptions.IgnoreCase);\n\nstatic bool IsValidSecondaryAxis(string v)\n{\n    if (string.IsNullOrWhiteSpace(v)) return true; // no-op\n    if (v.Equals(\"true\", StringComparison.OrdinalIgnoreCase)) return true;\n    if (v.Equals(\"false\", StringComparison.OrdinalIgnoreCase)) return true;\n    if (v.Equals(\"none\", StringComparison.OrdinalIgnoreCase)) return true;\n    foreach (var part in v.Split(','))\n    {\n        var t = part.Trim();\n        if (int.TryParse(t, out var n) && n > 0) continue;\n        if (SeriesAlias.IsMatch(t)) continue;\n        return false; // type-name form must be validated against the chart's series\n    }\n    return true;\n}","typeGuard":"static bool IsIndexOrAlias(string v) =>\n    (int.TryParse(v, out var n) && n > 0)\n    || SeriesAlias.IsMatch(v);","tryCatchPattern":"try { SetChartProperties(part, props); }\ncatch (ArgumentException ex) when (ex.Message.StartsWith(\"Invalid 'secondaryAxis'\"))\n{ /* surface accepted forms to the user; indices are 1-based */ }","preventionTips":["Indices are 1-based — convert zero-based UIs by adding 1.","For type-name form, ensure the chart actually has a series of that type (combo chart).","Whitelist 'true'/'false'/'none' and seriesN aliases explicitly."],"tags":["ooxml","chart","input-validation","secondary-axis","combo-chart","csharp"],"backgroundTag":null,"analyzedSha":"1ced45e900782c5083ed550ddf328ee974e425e7","analyzedAt":"2026-08-13T13:01:07.193Z","schemaVersion":2},"datasetVersion":"2026-08-13T14:17:21.547Z"}