tui-cs/Terminal.Gui · error · JsonException

{value}: Invalid Rune. The second codepoint is not a combini

Error message

{value}: Invalid Rune. The second codepoint is not a combining mark: {cm}.

What it means

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.

Source

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

                        return result;
                    }

                    // Surrogate pair?
                    if (Rune.TryCreate ((char)first, (char)second, out result))
                    {
                        return result;
                    }

                    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))
                    {

View on GitHub (pinned to 2e47b11478)

Solutions

  1. Use a single codepoint for the Rune instead of two.
  2. If you want a combining sequence, make the second codepoint an actual combining mark (U+0300–U+036F, etc.).

Example fix

// before
"Key": "U+0041U+0042"
// after
"Key": "U+0041"
Defensive patterns

Strategy: validation

Validate before calling

static bool IsBasePlusCombining (uint first, uint second)
{
    var cat = System.Globalization.CharUnicodeInfo.GetUnicodeCategory ((int)second);
    return cat is System.Globalization.UnicodeCategory.NonSpacingMark
        or System.Globalization.UnicodeCategory.SpacingCombiningMark
        or System.Globalization.UnicodeCategory.EnclosingMark;
}

Try / catch

try { ConfigurationManager.Apply (); }
catch (JsonException ex) when (ex.Message.Contains ("not a combining mark"))
{ /* report offending value from ex.Message */ }

Prevention

When it happens

Trigger: Config gives two regular characters (e.g. "U+0041U+0042" = "AB") — neither a surrogate pair nor base+combining-mark.

Common situations: Accidentally putting two glyphs into one Rune field; assuming any two characters concatenate into a single Rune.

Related errors


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