AvaloniaUI/Avalonia · error · ArgumentException

Output span must be at least as long as input span

Error message

Output span must be at least as long as input span

What it means

GlyphTypeface.TryGetGlyphMetrics(ReadOnlySpan<ushort> glyphIds, Span<GlyphMetrics> metrics) writes one GlyphMetrics per glyph id, so the output span must be at least as long as the input. The guard prevents writing past the end of the caller's buffer.

Source

Thrown at src/Avalonia.Base/Media/GlyphTypeface.cs:764

            return true;
        }

        /// <summary>
        /// Attempts to retrieve glyph metrics for multiple glyphs in a single operation.
        /// </summary>
        /// <remarks>This method is significantly more efficient than calling <see cref="TryGetGlyphMetrics(ushort, out GlyphMetrics)"/>
        /// multiple times as it minimizes memory access overhead and exploits data locality. This is the preferred
        /// method for batch glyph metrics retrieval in text layout and rendering scenarios. Returns false if neither
        /// horizontal nor vertical metrics are available.</remarks>
        /// <param name="glyphIds">Read-only span of glyph identifiers for which to retrieve metrics.</param>
        /// <param name="metrics">Output span to write the glyph metrics. Must be at least as long as <paramref name="glyphIds"/>.</param>
        /// <returns>true if metrics are available and all were successfully retrieved; otherwise, false.</returns>
        public bool TryGetGlyphMetrics(ReadOnlySpan<ushort> glyphIds, Span<GlyphMetrics> metrics)
        {
            if (metrics.Length < glyphIds.Length)
            {
                throw new ArgumentException("Output span must be at least as long as input span", nameof(metrics));
            }

            if (!_hasHorizontalMetrics && !_hasVerticalMetrics)
            {
                return false;
            }

            // Use stackalloc for temporary buffers to avoid heap allocations
            Span<HorizontalGlyphMetric> hMetrics = glyphIds.Length <= 256
                ? stackalloc HorizontalGlyphMetric[glyphIds.Length]
                : new HorizontalGlyphMetric[glyphIds.Length];

            Span<VerticalGlyphMetric> vMetrics = glyphIds.Length <= 256
                ? stackalloc VerticalGlyphMetric[glyphIds.Length]
                : new VerticalGlyphMetric[glyphIds.Length];

            bool hasHorizontal = false;
            bool hasVertical = false;

View on GitHub (pinned to 11c5427268)

Solutions

  1. Allocate the output span from the input length: Span<GlyphMetrics> dst = new GlyphMetrics[glyphIds.Length];
  2. If pooling, rent a buffer of size >= glyphIds.Length and slice to that length.
  3. Add an assertion before the call: Debug.Assert(metrics.Length >= glyphIds.Length).
  4. Refactor so callers always derive the destination length from the source.

Example fix

// before
var dst = new GlyphMetrics[32]; // fixed size; batch > 32 throws
if (gt.TryGetGlyphMetrics(glyphIds, dst)) { ... }

// after
Span<GlyphMetrics> dst = glyphIds.Length <= 64
    ? stackalloc GlyphMetrics[glyphIds.Length]
    : new GlyphMetrics[glyphIds.Length];
if (gt.TryGetGlyphMetrics(glyphIds, dst)) { ... }
Defensive patterns

Strategy: validation

Validate before calling

Span<GlyphMetrics> dst = glyphIds.Length <= 64
    ? stackalloc GlyphMetrics[glyphIds.Length]
    : new GlyphMetrics[glyphIds.Length];
Debug.Assert(dst.Length >= glyphIds.Length);
gt.TryGetGlyphMetrics(glyphIds, dst);

Prevention

When it happens

Trigger: Allocating the output span with the wrong length (e.g. glyphIds.Length / 2); reusing a pre-sized buffer that is too small for the current request; passing a stackalloc sized against a different constant.

Common situations: Batching glyph lookups and sizing the destination from a cached value rather than the live input length; off-by-one in array allocation; reusing a buffer pool sized for a previous, smaller batch.

Related errors


AI-assisted analysis of AvaloniaUI/Avalonia@11c5427268 (2026-08-13). Data as JSON: /api/errors/fca0cb61a3fb26ee. Report an issue: GitHub.