{"record":{"id":"7d7a8d35461998d0","repo":"iOfficeAI/OfficeCLI","slug":"fullkey-expected-boolean-true-false-1-0-yes-no","errorCode":null,"errorMessage":"{fullKey}: expected boolean (true/false/1/0/yes/no/on/off), got '{value}'.","messagePattern":"(.+?): expected boolean \\(true/false/1/0/yes/no/on/off\\), got '(.+?)'\\.","errorType":"validation","errorClass":"ArgumentException","httpStatus":null,"severity":"error","filePath":"src/officecli/Core/Chart/ChartHelper.Setter.cs","lineNumber":4509,"sourceCode":"    private static void ValidateTrendlineOptionValue(string subKey, string value, string fullKey)\n    {\n        switch (subKey)\n        {\n            case \"name\" or \"label\":\n                break; // any string is valid\n            case \"forward\" or \"forecastforward\"\n                or \"backward\" or \"forecastbackward\"\n                or \"intercept\":\n                ParseHelpers.SafeParseDouble(value, fullKey);\n                break;\n            case \"order\" or \"period\":\n                ParseHelpers.SafeParseInt(value, fullKey);\n                break;\n            case \"disprsqr\" or \"rsquared\" or \"r2\" or \"displayrsquared\"\n                or \"dispeq\" or \"equation\" or \"displayequation\":\n                var v = (value ?? \"\").Trim().ToLowerInvariant();\n                if (v is not (\"true\" or \"false\" or \"1\" or \"0\" or \"yes\" or \"no\" or \"on\" or \"off\"))\n                    throw new ArgumentException(\n                        $\"{fullKey}: expected boolean (true/false/1/0/yes/no/on/off), got '{value}'.\");\n                break;\n        }\n    }\n\n    // R8-3: previously the dotted show* / top-level show* setters only flipped\n    // existing <c:dLbls> containers. On a chart whose data labels had been\n    // cleared (datalabels=none, or new charts emitted without dLbls), the\n    // Descendants<DataLabels> enumeration returned nothing and the operation\n    // succeeded silently with no XML change. Caller saw success=true and an\n    // unchanged chart — surprise round-trip behaviour. Enable-by-show*\n    // semantics expect us to materialise a minimal container when one is\n    // missing; collect (and seed if needed) the DataLabels for each chartType\n    // in the PlotArea.\n    private static bool EnsureDataLabelsForShowToggle(\n        C.Chart chart, string key, List<string> unsupported, out List<C.DataLabels> dataLabels)\n    {\n        dataLabels = new List<C.DataLabels>();","sourceCodeStart":4491,"sourceCodeEnd":4527,"githubUrl":"https://github.com/iOfficeAI/OfficeCLI/blob/1ced45e900782c5083ed550ddf328ee974e425e7/src/officecli/Core/Chart/ChartHelper.Setter.cs#L4491-L4527","documentation":"Thrown by ValidateTrendlineOptionValue (ChartHelper.Setter.cs:4509) when a trendline display-flag sub-key — dispRsqr, rsquared, r2, displayrsquared, dispeq, equation, displayequation — receives a value that is not one of the eight literal boolean tokens true/false/1/0/yes/no/on/off. This is a parse-only pre-validation pass (fuzz-TL01/TL02) so the bad value is rejected even when the chart has no trendline element to apply it to yet. The validator's accepted set is deliberately narrow and exact-matches after Trim+ToLowerInvariant.","triggerScenarios":"Setting series1.trendline.displayRSquared=show, chart.trendline.displayEquation=enabled, or any dispRsqr/dispEq alias to a value outside {true,false,1,0,yes,no,on,off}, e.g. 'Y', 'on ' (trailing space untrimmed by caller), '2', 'enable'.","commonSituations":"UI code passing 'show'/'hide' or 'enabled'/'disabled' without mapping to the canonical tokens; booleans copied from localized data; stray whitespace or mixed casing that the caller did not normalize.","solutions":["Pass one of the accepted tokens literally: true, false, 1, 0, yes, no, on, off.","Trim and ToLowerInvariant the value client-side before setting the property so stray casing/whitespace cannot trip the exact match.","Map any upstream boolean to 'true'/'false' before forwarding it as the option value."],"exampleFix":"// before\nseries1.trendline.displayRSquared=show\n// after\nseries1.trendline.displayRSquared=true","handlingStrategy":"validation","validationCode":"static readonly HashSet<string> TrendlineBoolTokens = new(StringComparer.OrdinalIgnoreCase)\n{ \"true\",\"false\",\"1\",\"0\",\"yes\",\"no\",\"on\",\"off\" };\nstatic string NormalizeTrendlineBool(string v)\n{\n    var t = (v ?? \"\").Trim().ToLowerInvariant();\n    return TrendlineBoolTokens.Contains(t) ? t : throw new ArgumentException($\"expected boolean token, got '{v}'\");\n}","typeGuard":"static bool IsTrendlineBoolToken(string v) =>\n    TrendlineBoolTokens.Contains((v ?? \"\").Trim().ToLowerInvariant());","tryCatchPattern":"try { /* set chart series1.trendline.displayRSquared=... */ }\ncatch (ArgumentException ex) when (ex.Message.Contains(\"expected boolean\"))\n{ /* surface to user: list accepted tokens */ }","preventionTips":["Centralize boolean-to-token mapping in one helper so all call sites use the canonical set.","Trim and ToLowerInvariant user input before forwarding it as a trendline display flag.","Unit-test the validator against the exact 8-token set to catch drift."],"tags":["chart","trendline","boolean","validation"],"backgroundTag":null,"analyzedSha":"1ced45e900782c5083ed550ddf328ee974e425e7","analyzedAt":"2026-08-13T13:01:07.193Z","schemaVersion":2},"datasetVersion":"2026-08-13T14:17:21.547Z"}