{"record":{"id":"8b95333f8871e8a6","repo":"tui-cs/Terminal.Gui","slug":"value-invalid-rune-the-second-codepoint-is-not-8b9533","errorCode":null,"errorMessage":"{value}: Invalid Rune. The second codepoint is not a combining mark: {cm}.","messagePattern":"(.+?): Invalid Rune\\. The second codepoint is not a combining mark: (.+?)\\.","errorType":"exception","errorClass":"JsonException","httpStatus":null,"severity":"error","filePath":"Terminal.Gui/Configuration/RuneJsonConverter.cs","lineNumber":108,"sourceCode":"                        return result;\n                    }\n\n                    // Surrogate pair?\n                    if (Rune.TryCreate ((char)first, (char)second, out result))\n                    {\n                        return result;\n                    }\n\n                    if (!Rune.IsValid (second))\n                    {\n                        throw new JsonException ($\"{value}: Invalid Rune. The second codepoint is not valid: {second}.\");\n                    }\n\n                    var cm = new Rune (second);\n\n                    if (!cm.IsCombiningMark ())\n                    {\n                        throw new JsonException ($\"{value}: Invalid Rune. The second codepoint is not a combining mark: {cm}.\");\n                    }\n\n                    // not a surrogate pair, so a combining mark + char?\n                    string combined = string.Concat ((char)first, (char)second).Normalize ();\n\n                    if (!Rune.IsValid (combined [0]))\n                    {\n                        throw new JsonException ($\"{value}: Invalid combined Rune.\");\n                    }\n\n                    return new (combined [0]);\n                }\n            case JsonTokenType.Number:\n                {\n                    uint num = reader.GetUInt32 ();\n\n                    if (Rune.IsValid (num))\n                    {","sourceCodeStart":90,"sourceCodeEnd":126,"githubUrl":"https://github.com/tui-cs/Terminal.Gui/blob/2e47b11478db083499917f2ad27c34d30efb0df1/Terminal.Gui/Configuration/RuneJsonConverter.cs#L90-L126","documentation":"Two codepoints that are neither a surrogate pair nor a combining sequence: the second codepoint IS a valid scalar, but it is not a Unicode combining mark (General_Category Mn/Me/Mc). The converter only accepts a two-codepoint sequence as base+combining-mark; any other pair is rejected.","triggerScenarios":"Config gives two regular characters (e.g. \"U+0041U+0042\" = \"AB\") — neither a surrogate pair nor base+combining-mark.","commonSituations":"Accidentally putting two glyphs into one Rune field; assuming any two characters concatenate into a single Rune.","solutions":["Use a single codepoint for the Rune instead of two.","If you want a combining sequence, make the second codepoint an actual combining mark (U+0300–U+036F, etc.)."],"exampleFix":"// before\n\"Key\": \"U+0041U+0042\"\n// after\n\"Key\": \"U+0041\"","handlingStrategy":"validation","validationCode":"static bool IsBasePlusCombining (uint first, uint second)\n{\n    var cat = System.Globalization.CharUnicodeInfo.GetUnicodeCategory ((int)second);\n    return cat is System.Globalization.UnicodeCategory.NonSpacingMark\n        or System.Globalization.UnicodeCategory.SpacingCombiningMark\n        or System.Globalization.UnicodeCategory.EnclosingMark;\n}","typeGuard":null,"tryCatchPattern":"try { ConfigurationManager.Apply (); }\ncatch (JsonException ex) when (ex.Message.Contains (\"not a combining mark\"))\n{ /* report offending value from ex.Message */ }","preventionTips":["Remember a Rune is a single grapheme base, optionally plus one combining mark.","Avoid multi-character strings in Rune config fields."],"tags":["config","json","unicode","rune"],"backgroundTag":null,"analyzedSha":"2e47b11478db083499917f2ad27c34d30efb0df1","analyzedAt":"2026-08-13T19:20:08.826Z","schemaVersion":2},"datasetVersion":"2026-08-14T00:17:13.853Z"}