{"record":{"id":"73c9eda3f9b8e745","repo":"dotnet/wpf","slug":"sr-glyphsindexrequiredwithincluster","errorCode":null,"errorMessage":"SR.GlyphsIndexRequiredWithinCluster","messagePattern":"SR\\.GlyphsIndexRequiredWithinCluster","errorType":"validation","errorClass":"ArgumentException","httpStatus":null,"severity":"error","filePath":"src/Microsoft.DotNet.Wpf/src/PresentationFramework/System/Windows/Documents/Glyphs.cs","lineNumber":661,"sourceCode":"                            ++parsedCharacterCount;\n                        }\n                        parsedGlyphCount++;\n\n                        // initalize new per-glyph values\n                        valueWithinGlyph = 0; // which value we're on (how many commas have we seen in this glyph)?\n                        valueStartIndex = i + 1; // where (what index of Glyphs prop string) did this value start?\n                    }\n                }\n            }\n            #endregion\n\n            // fill the remaining glyphs with defaults, assuming 1:1 mapping\n            if (unicodeString != null)\n            {\n                while (parsedCharacterCount < unicodeString.Length)\n                {\n                    if (inCluster)\n                        throw new ArgumentException(SR.GlyphsIndexRequiredWithinCluster);\n\n                    if (unicodeString.Length <= parsedCharacterCount)\n                        throw new ArgumentException(SR.GlyphsUnicodeStringIsTooShort);\n\n                    parsedGlyphData.glyphIndex = GetGlyphFromCharacter(fontFace, unicodeString[parsedCharacterCount]);\n                    parsedGlyphData.advanceWidth = GetAdvanceWidth(fontFace, parsedGlyphData.glyphIndex, sideways);\n                    parsedGlyphs.Add(parsedGlyphData);\n                    parsedGlyphData = new ParsedGlyphData();\n                    SetClusterMapEntry(clusterMap, parsedCharacterCount, (ushort)parsedGlyphCount);\n                    ++parsedCharacterCount;\n                    ++parsedGlyphCount;\n                }\n            }\n\n            // return number of glyphs actually specified\n            return parsedGlyphCount;\n        }\n        #endregion Parsing and GlyphRun creation","sourceCodeStart":643,"sourceCodeEnd":679,"githubUrl":"https://github.com/dotnet/wpf/blob/81131a70a4c573cd62748a5c36908fc4d662daa9/src/Microsoft.DotNet.Wpf/src/PresentationFramework/System/Windows/Documents/Glyphs.cs#L643-L679","documentation":"Thrown by Glyphs.ParseGlyphsProperty in the final pass that fills remaining glyph defaults assuming 1:1 character-to-glyph mapping. If the parser is still inside a glyph cluster (inCluster == true) when characters remain in UnicodeString, an explicit glyph index is required for clustered characters — WPF will not guess glyphs inside a cluster — so it throws ArgumentException.","triggerScenarios":"A GlyphIndices string ending inside an unterminated cluster (e.g. \";(2:1\" or a cluster whose glyph count doesn't close) while UnicodeString still has unmatched characters, leaving the parser mid-cluster during default filling.","commonSituations":"Hand-edited GlyphIndices with an unclosed cluster bracket; cluster glyph counts miscounted so the cluster never terminates; truncated Indices strings from code generation.","solutions":["Ensure every cluster spec in GlyphIndices is complete and closed, e.g. \";(2:1)\".","Provide explicit glyph indices for all characters covered by clusters.","Verify that summed cluster glyph counts match the number of glyph entries in GlyphIndices."],"exampleFix":"<!-- before -->\n<Glyphs UnicodeString=\"abc\" GlyphIndices=\";(2:1\" />\n<!-- after -->\n<Glyphs UnicodeString=\"abc\" GlyphIndices=\";(2:1);10\" />","handlingStrategy":"validation","validationCode":"static bool ClustersClosed(string indices) { int open = indices.Count(c => c == '('), close = indices.Count(c => c == ')'); return open == close; }\nif (!ClustersClosed(glyphIndices)) throw new FormatException(\"Unterminated glyph cluster\");","typeGuard":"static bool NotEndingInCluster(string indices) { int depth = 0; foreach (char c in indices) { if (c == '(') depth++; if (c == ')') depth--; } return depth <= 0; }","tryCatchPattern":"try { glyphs.GlyphIndices = indices; }\ncatch (ArgumentException ex) when (ex.Message.Contains(\"cluster\")) { indices += \")\"; glyphs.GlyphIndices = indices; } // or reject and regenerate","preventionTips":["Close every '(n:m)' cluster before the next ';'","Balance-check brackets on generated Indices strings","Ensure cluster glyph counts terminate the cluster exactly where intended"],"tags":["wpf","glyphs","parsing","clusters","argumentexception"],"backgroundTag":"invalid-argument-format","analyzedSha":"81131a70a4c573cd62748a5c36908fc4d662daa9","analyzedAt":"2026-09-14T10:12:48.479Z","contentChangedAt":"2026-09-14T10:12:48.479Z","schemaVersion":2},"datasetVersion":"2026-09-21T21:30:21.729Z"}