tui-cs/Terminal.Gui · error · JsonException
{value}: Invalid Rune.
Error message
{value}: Invalid Rune. What it means
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).
Source
Thrown at Terminal.Gui/Configuration/RuneJsonConverter.cs:48
int first = RuneExtensions.MaxUnicodeCodePoint + 1;
int second = RuneExtensions.MaxUnicodeCodePoint + 1;
if (value is { } && (value.StartsWith ("U+", StringComparison.OrdinalIgnoreCase)
|| value.StartsWith ("\\U", StringComparison.OrdinalIgnoreCase)))
{
// Handle encoded single char, surrogate pair, or combining mark + char
uint [] codePoints = Regex.Matches (value, @"(?:\\[uU]\+?|U\+)([0-9A-Fa-f]{1,8})")
.Select (
match => uint.Parse (
match.Groups [1].Value,
NumberStyles.HexNumber
)
)
.ToArray ();
if (codePoints.Length is 0 or > 2)
{
throw new JsonException ($"{value}: Invalid Rune.");
}
if (codePoints.Length > 0)
{
first = (int)codePoints [0];
}
if (codePoints.Length == 2)
{
second = (int)codePoints [1];
}
}
else
{
// Handle single character, surrogate pair, or combining mark + char
if (value is { Length: 0 or > 2 })
{
throw new JsonException ($"{value}: Invalid Rune");View on GitHub (pinned to 2e47b11478)
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).
Example fix
// before (three codepoints) "Check": "U+1F600+1F601+1F602" // after (single codepoint) "Check": "U+1F600"
Defensive patterns
Strategy: validation
Validate before calling
using System.Text.RegularExpressions;
using System.Globalization;
static bool IsValidEncodedRune (string? value)
{
if (string.IsNullOrEmpty (value)) return false;
if (!(value!.StartsWith ("U+", StringComparison.OrdinalIgnoreCase)
|| value.StartsWith ("\\U", StringComparison.OrdinalIgnoreCase)))
return true; // literal form, handled separately
uint[] codePoints = Regex.Matches (value, @"(?:\[uU]\+?|U\+)([0-9A-Fa-f]{1,8})")
.Select (m => uint.Parse (m.Groups[1].Value, NumberStyles.HexNumber))
.ToArray ();
return codePoints.Length is 1 or 2;
}
if (!IsValidEncodedRune (runeValue))
{
// supply 1 or 2 valid codepoints
} Type guard
static bool IsValidEncodedRune (string? value)
{
if (string.IsNullOrEmpty (value)) return false;
if (!(value!.StartsWith ("U+", StringComparison.OrdinalIgnoreCase)
|| value.StartsWith ("\\U", StringComparison.OrdinalIgnoreCase)))
return true;
uint[] cps = Regex.Matches (value, @"(?:\[uU]\+?|U\+)([0-9A-Fa-f]{1,8})")
.Select (m => uint.Parse (m.Groups[1].Value, NumberStyles.HexNumber)).ToArray ();
return cps.Length is 1 or 2;
} Try / catch
try
{
ConfigurationManager.Load (configJson);
}
catch (JsonException ex) when (ex.Message.Contains ("Invalid Rune"))
{
// An encoded Rune had 0 or >2 codepoints. Supply 1-2 valid hex codepoints and reload.
} Prevention
- 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.
When it happens
Trigger: 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.
Common situations: 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).
Related errors
- {value}: Invalid Rune
- Expected a JSON array ("[ { ... } ]"), but got "{reader.Toke
- Expected start of array for Key[].
- Expected string token in Key array, got {reader.TokenType}.
- Unexpected end of JSON while reading Key array.
AI-assisted analysis of tui-cs/Terminal.Gui@2e47b11478 (2026-08-13).
Data as JSON: /api/errors/587880deda2a1a8f.
Report an issue: GitHub.