dotnet/wpf · error · ArgumentException
SR.GlyphsIndexRequiredWithinCluster
Error message
SR.GlyphsIndexRequiredWithinCluster
What it means
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.
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.
Example fix
<!-- before --> <Glyphs UnicodeString="abc" GlyphIndices=";(2:1" /> <!-- after --> <Glyphs UnicodeString="abc" GlyphIndices=";(2:1);10" />
Defensive patterns
Strategy: validation
Validate before calling
static bool ClustersClosed(string indices) { int open = indices.Count(c => c == '('), close = indices.Count(c => c == ')'); return open == close; }
if (!ClustersClosed(glyphIndices)) throw new FormatException("Unterminated glyph cluster"); Type guard
static bool NotEndingInCluster(string indices) { int depth = 0; foreach (char c in indices) { if (c == '(') depth++; if (c == ')') depth--; } return depth <= 0; } Try / catch
try { glyphs.GlyphIndices = indices; }
catch (ArgumentException ex) when (ex.Message.Contains("cluster")) { indices += ")"; glyphs.GlyphIndices = indices; } // or reject and regenerate Prevention
- 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
When it happens
Trigger: 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.
Common situations: Hand-edited GlyphIndices with an unclosed cluster bracket; cluster glyph counts miscounted so the cluster never terminates; truncated Indices strings from code generation.
Understand the failure class
Background: "Invalid ... format", "must be in format X", "does not look like a ..." — invalid argument format errors across CLI tools and libraries — this error's family across 17 libraries.
Related errors
- SR.GlyphsClusterMisplacedSeparator
- SR.GlyphsClusterNoMatchingBracket
- SR.GlyphsIndexRequiredIfNoUnicode
- SR.GlyphsTooManyCommas
- SR.GlyphsAdvanceWidthCannotBeNegative
AI-assisted analysis of dotnet/wpf@81131a70a4 (2026-09-14).
Data as JSON: /api/errors/73c9eda3f9b8e745.
Report an issue: GitHub.
Appendix: source
Thrown at src/Microsoft.DotNet.Wpf/src/PresentationFramework/System/Windows/Documents/Glyphs.cs:661
++parsedCharacterCount;
}
parsedGlyphCount++;
// initalize new per-glyph values
valueWithinGlyph = 0; // which value we're on (how many commas have we seen in this glyph)?
valueStartIndex = i + 1; // where (what index of Glyphs prop string) did this value start?
}
}
}
#endregion
// fill the remaining glyphs with defaults, assuming 1:1 mapping
if (unicodeString != null)
{
while (parsedCharacterCount < unicodeString.Length)
{
if (inCluster)
throw new ArgumentException(SR.GlyphsIndexRequiredWithinCluster);
if (unicodeString.Length <= parsedCharacterCount)
throw new ArgumentException(SR.GlyphsUnicodeStringIsTooShort);
parsedGlyphData.glyphIndex = GetGlyphFromCharacter(fontFace, unicodeString[parsedCharacterCount]);
parsedGlyphData.advanceWidth = GetAdvanceWidth(fontFace, parsedGlyphData.glyphIndex, sideways);
parsedGlyphs.Add(parsedGlyphData);
parsedGlyphData = new ParsedGlyphData();
SetClusterMapEntry(clusterMap, parsedCharacterCount, (ushort)parsedGlyphCount);
++parsedCharacterCount;
++parsedGlyphCount;
}
}
// return number of glyphs actually specified
return parsedGlyphCount;
}
#endregion Parsing and GlyphRun creationView on GitHub (pinned to 81131a70a4)