dotnet/wpf · error · ArgumentException
SR.Format(SR.CollectionNumberOfElementsShouldBeEqualTo…
Error message
SR.Format(SR.CollectionNumberOfElementsShouldBeEqualTo, characters.Count)
What it means
If the clusterMap is null or empty, GlyphRun.Initialize falls back to a 1:1 mapping assumption and requires clusterMap-length consistency with characters: in this branch (characters.Count == GlyphCount failing earlier checks) it demands the character count match. The message states the collection must have exactly characters.Count elements, thrown as ArgumentException on clusterMap.
Solutions
- Supply an explicit clusterMap that maps each character to glyph positions when counts differ
- Ensure characters.Count == glyphIndices.Count for simple 1:1 runs
- Use a text shaper (TextFormatter/ShapeableTextCharacters) to produce matching collections
Example fix
// before: 'ffi' ligature -> 1 glyph but 3 characters, no clusterMap
new GlyphRun(typeface, bidiLevel, isSideways, 12.0, glyphs, "ffi".ToCharArray(), null, ...);
// after: provide clusterMap {0,0,0}
new GlyphRun(typeface, bidiLevel, isSideways, 12.0, glyphs, "ffi".ToCharArray(), new int[]{0,0,0}, ...); Defensive patterns
Strategy: validation
Validate before calling
if (clusterMap == null || clusterMap.Length == 0)
{
if (characters.Count != glyphIndices.Count)
throw new InvalidOperationException("Provide a clusterMap when character and glyph counts differ");
} Type guard
static bool CanUseImplicitMap(char[] chars, ushort[] glyphs) => chars.Length == glyphs.Length;
Try / catch
try { var run = new GlyphRun(...); }
catch (ArgumentException ex) when (ex.ParamName == "clusterMap") { /* supply explicit clusterMap */ } Prevention
- Always supply a clusterMap for shaped text with ligatures or surrogates
- Shape text via TextFormatter rather than mapping chars to glyphs manually
- Assert characters.Count == glyphIndices.Count for simple runs
When it happens
Trigger: Constructing a GlyphRun via constructor, TryCreate, or EndInit where characters.Count != GlyphCount and no valid clusterMap is supplied, so the implicit mapping cannot be established.
Common situations: Passing pre-shaped glyph indices whose count differs from the number of Unicode characters (e.g. ligatures, surrogate pairs, combining marks) while leaving clusterMap null.
Understand the failure class
Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.
Related errors
- SR.ClusterMapEntriesShouldNotDecrease
- SR.ClusterMapEntryShouldPointWithinGlyphIndices
- SR.ClusterMapFirstEntryMustBeZero
- SR.CollectionNumberOfElementsMustBeGreaterThanZero
- SR.Format(SR.CollectionNumberOfElementsMustBeLessOrEqualTo…
AI-assisted analysis of dotnet/wpf@81131a70a4 (2026-09-14).
Data as JSON: /api/errors/ffc0a2aa222cf045.
Report an issue: GitHub.
Appendix: source
Thrown at src/Microsoft.DotNet.Wpf/src/PresentationCore/System/Windows/Media/GlyphRun.cs:398
}
else
{
if (clusterMap[i] < clusterMap[i - 1])
throw new ArgumentException(SR.ClusterMapEntriesShouldNotDecrease, nameof(clusterMap));
if (clusterMap[i] >= GlyphCount)
throw new ArgumentException(SR.ClusterMapEntryShouldPointWithinGlyphIndices, nameof(clusterMap));
}
}
}
else
{
throw new ArgumentException(SR.ClusterMapFirstEntryMustBeZero, nameof(clusterMap));
}
}
else
{
throw new ArgumentException(SR.Format(SR.CollectionNumberOfElementsShouldBeEqualTo, characters.Count), nameof(clusterMap));
}
}
else
{
if (GlyphCount != characters.Count)
throw new ArgumentException(SR.Format(SR.CollectionNumberOfElementsShouldBeEqualTo, GlyphCount), nameof(clusterMap));
}
}
if (caretStops != null && caretStops.Count != 0)
{
if (caretStops.Count != CodepointCount + 1)
throw new ArgumentException(SR.Format(SR.CollectionNumberOfElementsShouldBeEqualTo, CodepointCount + 1), nameof(caretStops));
}
if (isSideways && (bidiLevel & 1) != 0)
throw new ArgumentException(SR.SidewaysRTLTextIsNotSupported);
View on GitHub (pinned to 81131a70a4)