{"record":{"id":"ad1ffc1b0467315b","repo":"iOfficeAI/OfficeCLI","slug":"invalid-threshold-parts-i-in-colorrule","errorCode":null,"errorMessage":"Invalid threshold '{parts[i]}' in colorRule.","messagePattern":"Invalid threshold '(.+?)' in colorRule\\.","errorType":"validation","errorClass":"ArgumentException","httpStatus":null,"severity":"error","filePath":"src/officecli/Core/Chart/ChartHelper.Advanced.cs","lineNumber":322,"sourceCode":"        string topColor;\n\n        if (parts.Length == 3)\n        {\n            // Simple two-zone: threshold:belowColor:aboveColor\n            if (!double.TryParse(parts[0], System.Globalization.NumberStyles.Float,\n                System.Globalization.CultureInfo.InvariantCulture, out var t))\n                throw new ArgumentException($\"Invalid threshold '{parts[0]}' in colorRule. Expected a number.\");\n            rules.Add((t, parts[1].Trim()));\n            topColor = parts[2].Trim();\n        }\n        else\n        {\n            // Multi-zone: t1:c1:t2:c2:...:cN\n            for (int i = 0; i < parts.Length - 1; i += 2)\n            {\n                if (!double.TryParse(parts[i], System.Globalization.NumberStyles.Float,\n                    System.Globalization.CultureInfo.InvariantCulture, out var t))\n                    throw new ArgumentException($\"Invalid threshold '{parts[i]}' in colorRule.\");\n                rules.Add((t, parts[i + 1].Trim()));\n            }\n            topColor = parts.Length % 2 == 1 ? parts[^1].Trim() : rules[^1].color;\n            if (parts.Length % 2 == 0)\n                rules.RemoveAt(rules.Count - 1); // Last pair has no \"above\" — use as topColor\n        }\n\n        // Apply to each data point in each series\n        foreach (var ser in plotArea.Descendants<OpenXmlCompositeElement>().Where(e => e.LocalName == \"ser\"))\n        {\n            var values = ReadNumericData(ser.GetFirstChild<C.Values>())\n                ?? ReadNumericData(ser.Elements<OpenXmlCompositeElement>().FirstOrDefault(e => e.LocalName == \"yVal\"));\n            if (values == null) continue;\n\n            for (int pi = 0; pi < values.Length; pi++)\n            {\n                var val = values[pi];\n                string pointColor = topColor;","sourceCodeStart":304,"sourceCodeEnd":340,"githubUrl":"https://github.com/iOfficeAI/OfficeCLI/blob/1ced45e900782c5083ed550ddf328ee974e425e7/src/officecli/Core/Chart/ChartHelper.Advanced.cs#L304-L340","documentation":"In the multi-zone colorRule form (t1:c1:t2:c2:...:cN), every odd-indexed segment (parts[0], parts[2], ...) must be a numeric threshold. The parser iterates in steps of 2 and checks each threshold. If any threshold fails double.TryParse, the library rejects it with 'Invalid threshold'. This is the multi-zone path (parts.Length != 3); the simple path has its own error (error 128).","triggerScenarios":"Passing a multi-zone colorRule where any threshold segment is non-numeric: '0:FF0000:abc:00AA00' or 'x:FF0000:50:00AA00:100:FFFF00'. The spec must have more than 3 colon-separated parts.","commonSituations":"Mismatching the alternating threshold:color pattern — placing a color where a threshold belongs. Using locale-specific decimal separators. Adding an extra colon that shifts the even/odd alignment of segments.","solutions":["Ensure every odd-positioned segment (0-indexed: 0, 2, 4, ...) is a numeric threshold: '0:FF0000:50:FFAA00:100:00AA00'.","Verify the segment count matches the intended threshold:color pairs plus an optional trailing top color.","Check for accidental extra colons that misalign the threshold/color pattern."],"exampleFix":"// before\ncolorrule: \"0:FF0000:abc:00AA00:100:FFFF00\"\n// after\ncolorrule: \"0:FF0000:50:00AA00:100:FFFF00\"","handlingStrategy":"validation","validationCode":"static bool AreMultiZoneThresholdsNumeric(string spec)\n{\n    var parts = spec.Split(':');\n    if (parts.Length <= 3) return true; // not multi-zone\n    for (int i = 0; i < parts.Length - 1; i += 2)\n    {\n        if (!double.TryParse(parts[i], System.Globalization.NumberStyles.Float,\n            System.Globalization.CultureInfo.InvariantCulture, out _))\n            return false;\n    }\n    return true;\n}","typeGuard":null,"tryCatchPattern":"try { ChartHelperAdvanced.ApplyColorRule(plotArea, spec); }\ncatch (ArgumentException ex) when (ex.Message.Contains(\"Invalid threshold\") && !ex.Message.Contains(\"Expected a number\"))\n{\n    Console.Error.WriteLine($\"A threshold in multi-zone colorRule is non-numeric.\");\n}","preventionTips":["In multi-zone specs, every even-indexed segment (0, 2, 4, ...) must be numeric.","Maintain the alternating threshold:color:threshold:color pattern.","Count segments carefully — an extra colon shifts the alignment."],"tags":["chart","conditional-coloring","colorrule","number-parsing"],"backgroundTag":null,"analyzedSha":"1ced45e900782c5083ed550ddf328ee974e425e7","analyzedAt":"2026-08-13T13:01:07.193Z","schemaVersion":2},"datasetVersion":"2026-08-13T14:17:21.547Z"}