{"record":{"id":"eb0a7c75d276c78c","repo":"tui-cs/Terminal.Gui","slug":"only-valid-unicode-scalar-values-are-allowed-in-a","errorCode":null,"errorMessage":"Only valid Unicode scalar values are allowed in a single Grapheme cluster.","messagePattern":"Only valid Unicode scalar values are allowed in a single Grapheme cluster\\.","errorType":"validation","errorClass":"ArgumentException","httpStatus":null,"severity":"error","filePath":"Terminal.Gui/Drawing/Cell.cs","lineNumber":37,"sourceCode":"    private string _grapheme = Grapheme;\n\n    /// <summary>\n    ///     The single grapheme cluster to display from this cell. If <see cref=\"Grapheme\"/> is <see langword=\"null\"/> or\n    ///     <see cref=\"string.Empty\"/>, then <see cref=\"Cell\"/> is ignored.\n    /// </summary>\n    public string Grapheme\n    {\n        readonly get => _grapheme;\n        set\n        {\n            if (GraphemeHelper.GetGraphemeCount (value) > 1)\n            {\n                throw new InvalidOperationException ($\"Only a single {nameof (Grapheme)} cluster is allowed per Cell.\");\n            }\n\n            if (!string.IsNullOrEmpty (value) && value.Length == 1 && char.IsSurrogate (value [0]))\n            {\n                throw new ArgumentException ($\"Only valid Unicode scalar values are allowed in a single {nameof (Grapheme)} cluster.\");\n            }\n\n            try\n            {\n                _grapheme = !string.IsNullOrEmpty (value) && !value.IsNormalized (NormalizationForm.FormC)\n                                ? value.Normalize (NormalizationForm.FormC)\n                                : value;\n            }\n            catch (ArgumentException)\n            {\n                // leave text unnormalized\n                _grapheme = value;\n            }\n        }\n    }\n\n    /// <summary>\n    ///     The rune for <see cref=\"Grapheme\"/> or runes for <see cref=\"Grapheme\"/> that when combined makes this Cell a combining sequence.","sourceCodeStart":19,"sourceCodeEnd":55,"githubUrl":"https://github.com/tui-cs/Terminal.Gui/blob/2e47b11478db083499917f2ad27c34d30efb0df1/Terminal.Gui/Drawing/Cell.cs#L19-L55","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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."],"exampleFix":"// before - slices a surrogate pair\nCell c = new () { Grapheme = emoji [0].ToString () }; // throws if emoji is supplementary\n\n// after\nList<Cell> cells = Cell.ToCellList (emoji); // keeps the pair together as one Cell","handlingStrategy":"validation","validationCode":"// Reject lone surrogates before assigning\nif (value.Length == 1 && char.IsSurrogate (value [0]))\n    throw new ArgumentException (\"Use a complete surrogate pair / enumerate runes.\");","typeGuard":"static bool IsValidScalar (string s) => !(s.Length == 1 && char.IsSurrogate (s [0]));","tryCatchPattern":null,"preventionTips":["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."],"tags":["drawing","cell","unicode","surrogate","grapheme"],"backgroundTag":null,"analyzedSha":"2e47b11478db083499917f2ad27c34d30efb0df1","analyzedAt":"2026-08-13T19:20:08.826Z","schemaVersion":2},"datasetVersion":"2026-08-14T00:17:13.853Z"}