tui-cs/Terminal.Gui · error · InvalidOperationException
Only a single Grapheme cluster is allowed per Cell.
Error message
Only a single Grapheme cluster is allowed per Cell.
What it means
Thrown by the Cell.Grapheme setter when the assigned string contains more than one grapheme cluster (as counted by GraphemeHelper.GetGraphemeCount). A Cell models exactly one screen column and therefore holds exactly one user-perceived character (grapheme); assigning a multi-grapheme string like "ab" or "e\u0301e" violates that invariant.
Source
Thrown at Terminal.Gui/Drawing/Cell.cs:32
/// Gets or sets a value indicating whether this <see cref="T:Terminal.Gui.Drawing.Cell"/> has been modified since the
/// last time it was drawn.
/// </summary>
public bool IsDirty { get; set; } = IsDirty;
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;
}View on GitHub (pinned to 2e47b11478)
Solutions
- Use Cell.ToCellList(str, attribute) (or Cell.StringToCells) to split any string into one Cell per grapheme cluster — it uses GraphemeHelper.GetGraphemes internally.
- If you must assign manually, verify GraphemeHelper.GetGraphemeCount(value) <= 1 first.
- For combining sequences (base + combining marks), note those count as a SINGLE grapheme and are allowed; the error is only for 2+ clusters.
Example fix
// before
Cell cell = new () { Grapheme = "ab" }; // throws
// after
List<Cell> cells = Cell.ToCellList ("ab"); // [Cell{a}, Cell{b}] Defensive patterns
Strategy: validation
Validate before calling
// Confirm at most one grapheme cluster before assigning
if (GraphemeHelper.GetGraphemeCount (value) > 1)
throw new ArgumentException ("Use Cell.ToCellList to split multi-grapheme strings.");
cell.Grapheme = value; Type guard
static bool IsValidCellGrapheme (string s) => GraphemeHelper.GetGraphemeCount (s) <= 1;
Prevention
- Always convert strings to cells via Cell.ToCellList / Cell.StringToCells instead of assigning raw.
- Remember combining marks count as one grapheme and are allowed.
- Add a debug assertion on GraphemeHelper.GetGraphemeCount in cell-building code.
When it happens
Trigger: Directly assigning cell.Grapheme = "ab", or constructing new Cell { Grapheme = multiClusterString }, or a code path that pushes an unsplit string into a single Cell instead of a List<Cell>.
Common situations: Treating Cell like a general string holder; receiving user input and storing it in one cell instead of segmenting it; an off-by-one when slicing a string into cells.
Related errors
- Only valid Unicode scalar values are allowed in a single Gra
- {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/a045a55415875044.
Report an issue: GitHub.