{"record":{"id":"9ef291b939f79da9","repo":"iOfficeAI/OfficeCLI","slug":"invalid-boolean-value-value-expected-true-fa","errorCode":null,"errorMessage":"Invalid boolean value: '{value}'. Expected true/false, yes/no, 1/0, or on/off.","messagePattern":"Invalid boolean value: '(.+?)'\\. Expected true/false, yes/no, 1/0, or on/off\\.","errorType":"exception","errorClass":"ArgumentException","httpStatus":null,"severity":"error","filePath":"src/officecli/Core/ParseHelpers.cs","lineNumber":311,"sourceCode":"        9 => \"accent6\",\n        10 => \"hlink\",\n        11 => \"folHlink\",\n        _ => null,\n    };\n\n    /// <summary>\n    /// Returns true if the value is a recognized boolean string and is truthy.\n    /// Returns false for null, empty, or recognized falsy values (\"false\", \"0\", \"no\", \"off\").\n    /// Throws <see cref=\"ArgumentException\"/> for non-null values that are not recognized boolean strings.\n    /// </summary>\n    public static bool IsTruthy(string? value)\n    {\n        if (value == null) return false;\n        return TrimInvisible(value).ToLowerInvariant() switch\n        {\n            \"true\" or \"1\" or \"yes\" or \"on\" => true,\n            \"false\" or \"0\" or \"no\" or \"off\" or \"\" => false,\n            _ => throw new ArgumentException(\n                $\"Invalid boolean value: '{value}'. Expected true/false, yes/no, 1/0, or on/off.\")\n        };\n    }\n\n    // R10: BOM (U+FEFF) and other zero-width / format chars are NOT in\n    // char.IsWhiteSpace, so a plain Trim() leaves them in place. R8 added\n    // Trim() but tests with `\"﻿true\"` still threw. Use a stricter\n    // predicate that also drops format/control chars.\n    private static string TrimInvisible(string s)\n    {\n        return s.Trim().Trim(s_invisibleChars);\n    }\n\n    private static readonly char[] s_invisibleChars =\n    {\n        '﻿', // BOM / zero-width no-break space\n        '​', // zero-width space\n        '‌', // zero-width non-joiner","sourceCodeStart":293,"sourceCodeEnd":329,"githubUrl":"https://github.com/iOfficeAI/OfficeCLI/blob/1ced45e900782c5083ed550ddf328ee974e425e7/src/officecli/Core/ParseHelpers.cs#L293-L329","documentation":"Thrown by IsTruthy when the value is a non-null, non-empty string that is not one of the recognized boolean tokens (true/false/yes/no/1/0/on/off). IsTruthy deliberately rejects ambiguous strings instead of guessing, so that a misspelled flag fails loudly rather than being treated as false. The comparison is case-insensitive and trims BOM/zero-width/format chars first.","triggerScenarios":"Passing \"maybe\", \"enable\", \"y\", \"t\", or a localized yes/no. Also a value like \"true \" with non-breaking spaces would be handled by the strict trim, but unusual control chars combined with text could still miss.","commonSituations":"Flag values coming from user-typed CLI args ('y' instead of 'yes'); localized configs; values like 'enabled'/'disabled' from a different schema.","solutions":["Use one of the canonical tokens: true/false, yes/no, 1/0, on/off.","Map your custom vocabulary to a canonical token before calling IsTruthy.","If unknown should mean false (not an error), catch ArgumentException or pre-check membership."],"exampleFix":"// before\nvar enabled = ParseHelpers.IsTruthy(userInput); // userInput == \"enabled\"\n\n// after\nvar map = new Dictionary<string,bool>(StringComparer.OrdinalIgnoreCase)\n{\n    [\"enabled\"]=true, [\"disabled\"]=false\n};\nvar enabled = map.TryGetValue(userInput, out var b) ? b : ParseHelpers.IsTruthy(userInput);","handlingStrategy":"type-guard","validationCode":"static readonly HashSet<string> BoolTokens = new(StringComparer.OrdinalIgnoreCase)\n{ \"true\",\"false\",\"yes\",\"no\",\"1\",\"0\",\"on\",\"off\" };\nif (!BoolTokens.Contains(value)) value = \"false\";","typeGuard":"static bool IsRecognizedBool(string? v)\n    => v != null && BoolTokens.Contains(v.Trim().ToLowerInvariant());","tryCatchPattern":"bool enabled;\ntry { enabled = ParseHelpers.IsTruthy(raw); }\ncatch (ArgumentException) { enabled = false; Console.Error.WriteLine($\"unrecognized flag '{raw}'\"); }","preventionTips":["Restrict flag inputs to the canonical token set.","Map custom vocabularies to canonical tokens upstream.","Decide explicitly whether unknown means false or an error."],"tags":["boolean","validation","argument","parsing"],"backgroundTag":null,"analyzedSha":"1ced45e900782c5083ed550ddf328ee974e425e7","analyzedAt":"2026-08-13T13:01:07.193Z","schemaVersion":2},"datasetVersion":"2026-08-13T14:17:21.547Z"}