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

  1. Supply an explicit clusterMap that maps each character to glyph positions when counts differ
  2. Ensure characters.Count == glyphIndices.Count for simple 1:1 runs
  3. 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

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


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)