tui-cs/Terminal.Gui · error · ArgumentException
Only valid Unicode scalar values are allowed in a single Gra
Error message
Only valid Unicode scalar values are allowed in a single Grapheme cluster.
What it means
Thrown by the Cell.Grapheme setter when the value is a 1-character string whose single char is a Unicode surrogate (char.IsSurrogate returns true). A lone surrogate is not a valid Unicode scalar value; valid supplementary characters must be passed as a complete surrogate pair (which has length 2 and is one grapheme cluster, allowed by the prior check). This guards against corrupt strings produced by naive char-by-char slicing.
Source
Thrown at Terminal.Gui/Drawing/Cell.cs:37
private string _grapheme = Grapheme;
/// <summary>
/// The single grapheme cluster to display from this cell. If <see cref="Grapheme"/> is <see langword="null"/> or
/// <see cref="string.Empty"/>, then <see cref="Cell"/> is ignored.
/// </summary>
public string Grapheme
{
readonly get => _grapheme;
set
{
if (GraphemeHelper.GetGraphemeCount (value) > 1)
{
throw new InvalidOperationException ($"Only a single {nameof (Grapheme)} cluster is allowed per Cell.");
}
if (!string.IsNullOrEmpty (value) && value.Length == 1 && char.IsSurrogate (value [0]))
{
throw new ArgumentException ($"Only valid Unicode scalar values are allowed in a single {nameof (Grapheme)} cluster.");
}
try
{
_grapheme = !string.IsNullOrEmpty (value) && !value.IsNormalized (NormalizationForm.FormC)
? value.Normalize (NormalizationForm.FormC)
: value;
}
catch (ArgumentException)
{
// leave text unnormalized
_grapheme = value;
}
}
}
/// <summary>
/// The rune for <see cref="Grapheme"/> or runes for <see cref="Grapheme"/> that when combined makes this Cell a combining sequence.View on GitHub (pinned to 2e47b11478)
Solutions
- Enumerate graphemes (StringInfo, GraphemeHelper.GetGraphemes) or runes (str.EnumerateRunes()) instead of indexing chars, so supplementary characters stay intact.
- Validate with value.Length != 1 || !char.IsSurrogate(value[0]) before assigning.
- Use Cell.ToCellList to convert any string to cells safely regardless of encoding.
Example fix
// before - slices a surrogate pair
Cell c = new () { Grapheme = emoji [0].ToString () }; // throws if emoji is supplementary
// after
List<Cell> cells = Cell.ToCellList (emoji); // keeps the pair together as one Cell Defensive patterns
Strategy: validation
Validate before calling
// Reject lone surrogates before assigning
if (value.Length == 1 && char.IsSurrogate (value [0]))
throw new ArgumentException ("Use a complete surrogate pair / enumerate runes."); Type guard
static bool IsValidScalar (string s) => !(s.Length == 1 && char.IsSurrogate (s [0]));
Prevention
- Enumerate runes (str.EnumerateRunes ()) or graphemes rather than indexing chars.
- Use Cell.ToCellList for any string of unknown encoding.
- Add a debug assert that a 1-char grapheme is not a surrogate.
When it happens
Trigger: Slicing a string that contains an emoji or CJK extension character into chars and assigning one surrogate half to a Cell — e.g. grapheme = str[someIndex].ToString() where str[someIndex] is a high or low surrogate.
Common situations: Using String.Substring/[] indexing on a string with supplementary-plane characters instead of a grapheme/rune-aware API; reading bytes from a mis-decoded stream; a faulty text editor that split a pair.
Related errors
- Only a single Grapheme cluster is allowed per Cell.
- {value}: Invalid Rune.
- {value}: Invalid Rune
- {value}: Invalid Rune. The second codepoint is not valid: {s
- {value}: Invalid Rune. The second codepoint is not a combini
AI-assisted analysis of tui-cs/Terminal.Gui@2e47b11478 (2026-08-13).
Data as JSON: /api/errors/eb0a7c75d276c78c.
Report an issue: GitHub.