dotnet/wpf · error · ArgumentException

SR.CollectionNumberOfElementsMustBeGreaterThanZero

Error message

SR.CollectionNumberOfElementsMustBeGreaterThanZero

What it means

GlyphTypeface.ComputeSubset throws ArgumentException with SR.CollectionNumberOfElementsMustBeGreaterThanZero when the glyphs collection is empty. ComputeSubset produces a subsetted font binary for a supplied list of glyph indices; an empty list yields a meaningless (or invalid) font file, so it is rejected up front.

Solutions

  1. Check glyphs.Count > 0 before calling ComputeSubset and skip subsetting entirely when empty
  2. Populate the collection with actual glyph indices via GlyphTypeface.CharacterToGlyphMap before subsetting
  3. If subsetting for empty text, short-circuit and reuse or omit the font resource

Example fix

// before
glyphTypeface.ComputeSubset(outStream, new ushort[0]);
// after
if (glyphs.Count > 0)
    glyphTypeface.ComputeSubset(outStream, glyphs);
else
    /* skip subsetting or copy full font */;
Defensive patterns

Strategy: validation

Validate before calling

if (glyphs == null || glyphs.Count == 0)
    return; // nothing to subset

glyphTypeface.ComputeSubset(outStream, glyphs);

Try / catch

try { glyphTypeface.ComputeSubset(outStream, glyphs); }
catch (ArgumentException ex) when (ex.ParamName == "glyphs")
{
    log.Warn("Subset skipped: empty glyph collection", ex);
}

Prevention

When it happens

Trigger: Calling ComputeSubset(Stream, ICollection<ushort>) with a glyphs collection that has Count == 0, typically because the set of glyphs used by the text was computed to be empty (no text, or all characters mapped to no glyphs).

Common situations: Subsetting fonts for download/embedding scenarios where the input text is an empty string; a bug upstream that skips glyph collection; passing a filtered glyph list that removed everything (e.g. filtering out glyphs < 0xFFFF).

Understand the failure class

Background: "must not be empty", "cannot be empty" — required-field validation errors across open-source libraries — this error's family across 41 libraries.

Related errors


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

Appendix: source

Thrown at src/Microsoft.DotNet.Wpf/src/PresentationCore/System/Windows/Media/GlyphTypeface.cs:228

        /// <summary>
        /// Returns the binary image of font subset.
        /// </summary>
        /// <param name="glyphs">Collection of glyph indices to be included into the subset.</param>
        /// <returns>Binary image of font subset.</returns>
        /// <remarks>
        ///     Callers must have UnmanagedCode permission to call this API.
        ///     Callers must have FileIOPermission or WebPermission to font location to call this API.
        /// </remarks>
        [CLSCompliant(false)]
        public byte[] ComputeSubset(ICollection<ushort> glyphs)
        {
            CheckInitialized(); // This can only be called on fully initialized GlyphTypeface

            ArgumentNullException.ThrowIfNull(glyphs);

            if (glyphs.Count <= 0)
                throw new ArgumentException(SR.CollectionNumberOfElementsMustBeGreaterThanZero, nameof(glyphs));

            if (glyphs.Count > ushort.MaxValue)
                throw new ArgumentException(SR.Format(SR.CollectionNumberOfElementsMustBeLessOrEqualTo, ushort.MaxValue), nameof(glyphs));

            UnmanagedMemoryStream pinnedFontSource = FontSource.GetUnmanagedStream();

            try
            {
                TrueTypeFontDriver trueTypeDriver = new TrueTypeFontDriver(pinnedFontSource, _originalUri);
                trueTypeDriver.SetFace(FaceIndex);

                return trueTypeDriver.ComputeFontSubset(glyphs);
            }
            catch (SEHException e)
            {
                throw Util.ConvertInPageException(FontSource, e);
            }
            finally

View on GitHub (pinned to 81131a70a4)