{"record":{"id":"5c1f2cb827f1ede3","repo":"microsoft/aspire","slug":"cannot-convert-string-value-to-boolean-for-key-key-expected","errorCode":null,"errorMessage":"Cannot convert string '{value}' to boolean for key '{key}'. Expected 'true' or 'false'.","messagePattern":"Cannot convert string '(.+?)' to boolean for key '(.+?)'\\. Expected 'true' or 'false'\\.","errorType":"exception","errorClass":"JsonException","httpStatus":null,"severity":"error","filePath":"src/Aspire.Cli/Configuration/FlexibleBooleanDictionaryConverter.cs","lineNumber":84,"sourceCode":"            writer.WriteBoolean(kvp.Key, kvp.Value);\n        }\n\n        writer.WriteEndObject();\n    }\n\n    private static bool ParseBooleanString(string? value, string key)\n    {\n        if (string.Equals(value, \"true\", StringComparison.OrdinalIgnoreCase))\n        {\n            return true;\n        }\n\n        if (string.Equals(value, \"false\", StringComparison.OrdinalIgnoreCase))\n        {\n            return false;\n        }\n\n        throw new JsonException($\"Cannot convert string '{value}' to boolean for key '{key}'. Expected 'true' or 'false'.\");\n    }\n}\n","sourceCodeStart":66,"sourceCodeEnd":87,"githubUrl":"https://github.com/microsoft/aspire/blob/25830f84bd145686607ad00c057b3f84e2e51d43/src/Aspire.Cli/Configuration/FlexibleBooleanDictionaryConverter.cs#L66-L87","documentation":"ParseBooleanString is the converter's flexible-string helper: it accepts 'true' and 'false' case-insensitively and throws JsonException for any other string, including the key being parsed in the message. This is the strict core of the 'flexible' boolean support — only true/false strings flex.","triggerScenarios":"A string token in a Dictionary<string,bool> config object whose value is anything but 'true'/'false' in any casing, e.g. \"MyFeature\": \"yes\", \"1\", \"on\", \"enabled\", or \"\".","commonSituations":"Hand-edited config using natural-language booleans; values sourced from env vars or legacy config with 1/0 or yes/no conventions; documentation mismatch across tools.","solutions":["Edit the JSON value for the named key to be exactly 'true' or 'false' (any casing).","Trace where the value originates (env var, script, another tool) and make that source emit canonical booleans.","If broader acceptance is needed, extend ParseBooleanString with mappings (yes/1/on => true) before the throw."],"exampleFix":"// before\n\"featureFlags\": { \"MyFeature\": \"yes\" }\n// after\n\"featureFlags\": { \"MyFeature\": \"true\" }","handlingStrategy":"validation","validationCode":"static string? NormalizeBooleanString(string? s) =>\n    s is null ? null :\n    string.Equals(s, \"true\", StringComparison.OrdinalIgnoreCase) ? \"true\" :\n    string.Equals(s, \"false\", StringComparison.OrdinalIgnoreCase) ? \"false\" :\n    throw new FormatException($\"'{s}' is not a boolean; use 'true' or 'false'.\");","typeGuard":"static bool IsBooleanString(string? s) =>\n    s is not null &&\n    (string.Equals(s, \"true\", StringComparison.OrdinalIgnoreCase) ||\n     string.Equals(s, \"false\", StringComparison.OrdinalIgnoreCase));","tryCatchPattern":"try\n{\n    var config = JsonSerializer.Deserialize<MyConfig>(json, options);\n}\ncatch (JsonException ex) when (ex.Message.Contains(\"Cannot convert string\") && ex.Message.Contains(\"to boolean\"))\n{\n    logger.LogError(ex, \"Config boolean flags must be 'true'/'false' strings.\");\n}","preventionTips":["Write only 'true' or 'false' (any casing) as string booleans.","Canonicalize values from env vars/scripts before writing them into config.","Use unquoted true/false literals to avoid string parsing entirely."],"tags":["json","configuration","deserialization"],"backgroundTag":"invalid-config-value","analyzedSha":"25830f84bd145686607ad00c057b3f84e2e51d43","analyzedAt":"2026-09-16T11:10:06.193Z","contentChangedAt":"2026-09-16T11:10:06.193Z","schemaVersion":2},"datasetVersion":"2026-09-21T04:17:39.646Z"}