tui-cs/Terminal.Gui · error · JsonException

{value}: Invalid combined Rune.

Error message

{value}: Invalid combined Rune.

What it means

The rarest Rune path: two codepoints formed a valid base+combining-mark and were normalized via string.Normalize(), but the normalized result's first char is not a valid Rune (Rune.IsValid fails on combined[0]). This indicates the normalization produced an unexpected leading code unit.

Source

Thrown at Terminal.Gui/Configuration/RuneJsonConverter.cs:116

                    if (!Rune.IsValid (second))
                    {
                        throw new JsonException ($"{value}: Invalid Rune. The second codepoint is not valid: {second}.");
                    }

                    var cm = new Rune (second);

                    if (!cm.IsCombiningMark ())
                    {
                        throw new JsonException ($"{value}: Invalid Rune. The second codepoint is not a combining mark: {cm}.");
                    }

                    // not a surrogate pair, so a combining mark + char?
                    string combined = string.Concat ((char)first, (char)second).Normalize ();

                    if (!Rune.IsValid (combined [0]))
                    {
                        throw new JsonException ($"{value}: Invalid combined Rune.");
                    }

                    return new (combined [0]);
                }
            case JsonTokenType.Number:
                {
                    uint num = reader.GetUInt32 ();

                    if (Rune.IsValid (num))
                    {
                        return new (num);
                    }

                    throw new JsonException ($"{num}: Invalid Rune (not a scalar Unicode value).");
                }
            case JsonTokenType.Null:
                return default;
            default:

View on GitHub (pinned to 2e47b11478)

Solutions

  1. Use a precomposed (NFC) character instead of a base+combining pair (e.g. U+00E9 for é instead of U+0065+U+0301).
  2. Replace the pair with a single valid codepoint.

Example fix

// before
"Char": "U+0065U+0301"
// after
"Char": "U+00E9"
Defensive patterns

Strategy: validation

Validate before calling

static bool NormalizesToValidRune (char first, char second)
{
    string n = string.Concat (first, second).Normalize ();
    return n.Length > 0 && System.Text.Rune.IsValid (n [0]);
}

Try / catch

try { ConfigurationManager.Apply (); }
catch (JsonException ex) when (ex.Message.Contains ("Invalid combined Rune"))
{ /* report offending value from ex.Message */ }

Prevention

When it happens

Trigger: A base+combining-mark pair whose normalized form starts with a lone surrogate or otherwise invalid scalar — an edge case from unusual or malformed codepoint combinations.

Common situations: Extremely rare; only with exotic combining sequences or input that confuses Unicode normalization. Essentially a data-integrity edge case.

Related errors


AI-assisted analysis of tui-cs/Terminal.Gui@2e47b11478 (2026-08-13). Data as JSON: /api/errors/2561103629ad905a. Report an issue: GitHub.