dotnet/wpf · error · ArgumentException

SR.GlyphsIndexRequiredIfNoUnicode

Error message

SR.GlyphsIndexRequiredIfNoUnicode

What it means

Thrown by Glyphs.ParseGlyphsProperty while filling glyph defaults with a 1:1 character-to-glyph mapping. When no explicit glyph index was parsed for a character, the code derives the glyph from the corresponding UnicodeString character — but if UnicodeString is null or empty there is nothing to derive from. The parser requires either explicit glyph indices or a non-empty UnicodeString.

Solutions

  1. Set Glyphs.UnicodeString (or Characters) to a non-empty string when GlyphIndices omits any explicit glyph index.
  2. Provide an explicit glyph index for every comma-separated slot in GlyphIndices.
  3. Remove trailing/empty ';,' slots from the GlyphIndices string.

Example fix

<!-- before -->
<Glyphs GlyphIndices=";15;20" />
<!-- after -->
<Glyphs GlyphIndices=";15;20" UnicodeString="abc" />
Defensive patterns

Strategy: validation

Validate before calling

bool hasEmptySlotsNeedingUnicode = glyphIndices.Split(';').Any(string.IsNullOrEmpty);
if (hasEmptySlotsNeedingUnicode && string.IsNullOrEmpty(glyphs.UnicodeString))
    throw new InvalidOperationException("UnicodeString required when GlyphIndices omits explicit indices");

Type guard

static bool IndicesSelfContained(string indices) => indices.Split(';').Where(s => s.Length > 0).Count() == indices.Split(';').Count(s => s.Length == 0) ? false : true; // empty slots exist -> UnicodeString needed
// simpler: static bool NeedsUnicodeString(string indices) => indices != null && (indices.StartsWith(";") || indices.Contains(";;") || indices.EndsWith(";"));

Try / catch

try { glyphs.GlyphIndices = indices; }
catch (ArgumentException ex) when (string.IsNullOrEmpty(glyphs.UnicodeString)) { glyphs.UnicodeString = fallbackText; glyphs.GlyphIndices = indices; }

Prevention

When it happens

Trigger: Assigning Glyphs.GlyphIndices (or UnicodeString) such that some positions lack explicit indices while Glyphs.UnicodeString is null or empty — e.g. GlyphIndices="" with trailing ';' items, or Indices-only usage without setting UnicodeString/Characters.

Common situations: XAML Glyphs element that sets only GlyphIndices and forgets UnicodeString; data-bound or computed Indices strings that end with separators producing empty value slots.

Understand the failure class

Background: "missing required argument" and "the following required arguments were not provided": what required-argument errors mean and how to fix them — this error's family across 20 libraries.

Related errors


AI-assisted analysis of dotnet/wpf@81131a70a4 (2026-09-14). Data as JSON: /api/errors/7ada05588f8c39cc. Report an issue: GitHub.

Appendix: source

Thrown at src/Microsoft.DotNet.Wpf/src/PresentationFramework/System/Windows/Documents/Glyphs.cs:566

                        ReadOnlySpan<char> valueSpec = glyphsProp.AsSpan(valueStartIndex, len);

                        #region Interpret one comma-delimited value

                        switch (valueWithinGlyph)
                        {
                            case 0:
                                bool wasInCluster = inCluster;
                                // interpret cluster size and glyph index spec
                                if (!ReadGlyphIndex(
                                    valueSpec,
                                    ref inCluster,
                                    ref glyphClusterSize,
                                    ref characterClusterSize,
                                    ref parsedGlyphData.glyphIndex))
                                {
                                    if (String.IsNullOrEmpty(unicodeString))
                                        throw new ArgumentException(SR.GlyphsIndexRequiredIfNoUnicode);

                                    if (unicodeString.Length <= parsedCharacterCount)
                                        throw new ArgumentException(SR.GlyphsUnicodeStringIsTooShort);

                                    parsedGlyphData.glyphIndex = GetGlyphFromCharacter(fontFace, unicodeString[parsedCharacterCount]);
                                }

                                if (!wasInCluster && clusterMap != null)
                                {
                                    // fill out cluster map at the start of each cluster
                                    if (inCluster)
                                    {
                                        for (int ch = parsedCharacterCount; ch < parsedCharacterCount + characterClusterSize; ++ch)
                                        {
                                            SetClusterMapEntry(clusterMap, ch, (ushort)parsedGlyphCount);
                                        }
                                    }
                                    else

View on GitHub (pinned to 81131a70a4)