{"record":{"id":"587880deda2a1a8f","repo":"tui-cs/Terminal.Gui","slug":"value-invalid-rune","errorCode":null,"errorMessage":"{value}: Invalid Rune.","messagePattern":"(.+?): Invalid Rune\\.","errorType":"exception","errorClass":"JsonException","httpStatus":null,"severity":"error","filePath":"Terminal.Gui/Configuration/RuneJsonConverter.cs","lineNumber":48,"sourceCode":"                    int first = RuneExtensions.MaxUnicodeCodePoint + 1;\n                    int second = RuneExtensions.MaxUnicodeCodePoint + 1;\n\n                    if (value is { } && (value.StartsWith (\"U+\", StringComparison.OrdinalIgnoreCase)\n                                         || value.StartsWith (\"\\\\U\", StringComparison.OrdinalIgnoreCase)))\n                    {\n                        // Handle encoded single char, surrogate pair, or combining mark + char\n                        uint [] codePoints = Regex.Matches (value, @\"(?:\\\\[uU]\\+?|U\\+)([0-9A-Fa-f]{1,8})\")\n                                                  .Select (\n                                                           match => uint.Parse (\n                                                                                match.Groups [1].Value,\n                                                                                NumberStyles.HexNumber\n                                                                               )\n                                                          )\n                                                  .ToArray ();\n\n                        if (codePoints.Length is 0 or > 2)\n                        {\n                            throw new JsonException ($\"{value}: Invalid Rune.\");\n                        }\n\n                        if (codePoints.Length > 0)\n                        {\n                            first = (int)codePoints [0];\n                        }\n\n                        if (codePoints.Length == 2)\n                        {\n                            second = (int)codePoints [1];\n                        }\n                    }\n                    else\n                    {\n                        // Handle single character, surrogate pair, or combining mark + char\n                        if (value is { Length: 0 or > 2 })\n                        {\n                            throw new JsonException ($\"{value}: Invalid Rune\");","sourceCodeStart":30,"sourceCodeEnd":66,"githubUrl":"https://github.com/tui-cs/Terminal.Gui/blob/2e47b11478db083499917f2ad27c34d30efb0df1/Terminal.Gui/Configuration/RuneJsonConverter.cs#L30-L66","documentation":"Thrown by RuneJsonConverter.Read (RuneJsonConverter.cs:46-49) when a string value starts with 'U+'/'\\U' (encoded form) but the codepoint-extraction regex matched either zero captures or more than two captures. Zero means the prefix was present but no valid hex group followed; more than two means the string encodes 3+ codepoints, which cannot form a single Rune (max is a surrogate pair or char+combining-mark).","triggerScenarios":"A Rune config value is an encoded string like \"U+1F600+1F601+1F602\" (three codepoints) or \"U+ZZZZ\" (no valid hex digits, regex yields zero matches), or \"\\u\" alone with no hex. The regex (?:\\[uU]\\+?|U\\+)([0-9A-Fa-f]{1,8}) fails to produce 1 or 2 captures.","commonSituations":"User concatenates multiple U+ codepoints into one string expecting a grapheme cluster. User typos the hex digits. User copies a multi-codepoint emoji sequence into a single Rune field (Runes are single scalar values or char+combining-mark pairs, not arbitrary grapheme clusters).","solutions":["Provide at most two codepoints in the encoded string: one for a single scalar, or two for a surrogate pair / char+combining-mark combination.","Ensure at least one valid hexadecimal group follows U+/\\u (1-8 hex digits).","For a single emoji that is a multi-codepoint grapheme cluster (e.g. family emoji), pick a single-codepoint equivalent or store it differently — a Rune cannot hold a cluster of 3+.","Verify the hex digits are valid (0-9, A-F, a-f)."],"exampleFix":"// before (three codepoints)\n\"Check\": \"U+1F600+1F601+1F602\"\n\n// after (single codepoint)\n\"Check\": \"U+1F600\"","handlingStrategy":"validation","validationCode":"using System.Text.RegularExpressions;\nusing System.Globalization;\n\nstatic bool IsValidEncodedRune (string? value)\n{\n    if (string.IsNullOrEmpty (value)) return false;\n    if (!(value!.StartsWith (\"U+\", StringComparison.OrdinalIgnoreCase)\n          || value.StartsWith (\"\\\\U\", StringComparison.OrdinalIgnoreCase)))\n        return true; // literal form, handled separately\n\n    uint[] codePoints = Regex.Matches (value, @\"(?:\\[uU]\\+?|U\\+)([0-9A-Fa-f]{1,8})\")\n        .Select (m => uint.Parse (m.Groups[1].Value, NumberStyles.HexNumber))\n        .ToArray ();\n    return codePoints.Length is 1 or 2;\n}\n\nif (!IsValidEncodedRune (runeValue))\n{\n    // supply 1 or 2 valid codepoints\n}","typeGuard":"static bool IsValidEncodedRune (string? value)\n{\n    if (string.IsNullOrEmpty (value)) return false;\n    if (!(value!.StartsWith (\"U+\", StringComparison.OrdinalIgnoreCase)\n          || value.StartsWith (\"\\\\U\", StringComparison.OrdinalIgnoreCase)))\n        return true;\n    uint[] cps = Regex.Matches (value, @\"(?:\\[uU]\\+?|U\\+)([0-9A-Fa-f]{1,8})\")\n        .Select (m => uint.Parse (m.Groups[1].Value, NumberStyles.HexNumber)).ToArray ();\n    return cps.Length is 1 or 2;\n}","tryCatchPattern":"try\n{\n    ConfigurationManager.Load (configJson);\n}\ncatch (JsonException ex) when (ex.Message.Contains (\"Invalid Rune\"))\n{\n    // An encoded Rune had 0 or >2 codepoints. Supply 1-2 valid hex codepoints and reload.\n}","preventionTips":["Provide at most two codepoints in encoded Rune strings (single scalar or surrogate/combining pair).","Ensure at least one valid hex group follows U+/\\u.","Remember a Rune holds a single scalar value, not an arbitrary grapheme cluster.","Use the literal single-glyph form for simple characters."],"tags":["json","configuration","rune","unicode","serialization"],"backgroundTag":null,"analyzedSha":"2e47b11478db083499917f2ad27c34d30efb0df1","analyzedAt":"2026-08-13T19:20:08.826Z","schemaVersion":2},"datasetVersion":"2026-08-14T00:17:13.853Z"}