stride3d/stride · error · InvalidOperationException

The rendered character is too big for the cache texture

Error message

The rendered character is too big for the cache texture

What it means

The dynamic font atlas tries to insert the glyph rect via the packer; if it fails it evicts less-used characters, then clears the entire cache, and if insertion still fails, the glyph simply does not fit the fixed-size cache texture. It throws InvalidOperationException('The rendered character is too big for the cache texture') because no eviction strategy can help.

Solutions

  1. Increase the font atlas/cache texture size (render target settings for the font system)
  2. Reduce the font size or scale factor used to render the offending character
  3. Guard glyph size before upload: skip or pre-split characters whose bitmap exceeds atlas dimensions
  4. Ensure virtual resolution/DPI scaling is not inflating the requested glyph size unexpectedly

Example fix

// before
if (!packer.Insert(w, h, ref subrect)) { /* eventually throws */ }
// after
if (w > atlasSize.X || h > atlasSize.Y)
{
    log.Warning($"Glyph {character} too large ({w}x{h}) for atlas; skipping.");
    return;
}
packer.Insert(w, h, ref subrect);
Defensive patterns

Strategy: validation

Validate before calling

var size = new Int2(character.Bitmap.Width, character.Bitmap.Rows);
if (size.X > atlasWidth || size.Y > atlasHeight)
{
    log.Warning($"Glyph '{character.Character}' ({size.X}x{size.Y}) exceeds atlas; skipping.");
    return;
}

Type guard

bool FitsInAtlas(CharacterSpecification c, Int2 atlas) =>
    c?.Bitmap != null && c.Bitmap.Width <= atlas.X && c.Bitmap.Rows <= atlas.Y;

Try / catch

try { cache.UploadCharacterBitmap(commandList, character); }
catch (InvalidOperationException ex) when (ex.Message.Contains("too big for the cache texture"))
{
    log.Error($"Glyph '{character.Character}' exceeds atlas size. Increase cache size or reduce font scale.");
}

Prevention

When it happens

Trigger: Rendering a glyph whose pixel size (Width x Rows) exceeds the atlas texture dimensions — typically extremely large font sizes, huge scale factors, or a deliberately tiny cache texture size.

Common situations: A font rendered at very large point sizes (e.g. title text at 300pt+ on low-res virtual resolution); misconfigured font cache size; DPI/virtual-resolution scaling multiplying glyph size beyond the atlas.

Understand the failure class

Background: "value must be between 0 and 1" / "out of range" / "must not be negative" errors: fixing range-validation failures across open-source libraries — this error's family across 42 libraries.

Related errors


AI-assisted analysis of stride3d/stride@96fad776d2 (2026-09-14). Data as JSON: /api/errors/1221e5c4d21ba942. Report an issue: GitHub.

Appendix: source

Thrown at sources/engine/Stride.Graphics/Font/FontCacheManager.cs:83

        {
            if (character.Bitmap == null)
                throw new ArgumentNullException("character");

            if (character.IsBitmapUploaded)
                throw new InvalidOperationException($"The character '{character.Character}' upload has been requested while its current glyph is valid.");

            var targetSize = new Int2(character.Bitmap.Width, character.Bitmap.Rows);
            if (!packer.Insert(targetSize.X, targetSize.Y, ref character.Glyph.Subrect))
            {
                // not enough space to place the new character -> remove less used characters and try again
                RemoveLessUsedCharacters();
                if (!packer.Insert(targetSize.X, targetSize.Y, ref character.Glyph.Subrect))
                {
                    // memory is too fragmented in order to place the new character -> clear all the characters and restart.
                    // TODO: This is invalid, we might delete character from current frame!
                    ClearCache();
                    if (!packer.Insert(targetSize.X, targetSize.Y, ref character.Glyph.Subrect))
                        throw new InvalidOperationException("The rendered character is too big for the cache texture");
                }
            }
            // Upload the bitmap to the atlas texture, with a 1px transparent border extending
            // beyond the allocated region to clear any stale pixels from previously freed glyphs.
            // This overlaps into neighbors' transparent borders (which are also zeroed), so no
            // glyph data is corrupted. Prevents bilinear filtering artifacts when scaling fonts.
            if (character.Bitmap.Rows != 0 && character.Bitmap.Width != 0)
            {
                var texW = cacheTextures[0].ViewWidth;
                var texH = cacheTextures[0].ViewHeight;

                // Expand the upload region by 1px on each side, clamped to texture bounds
                int left = Math.Max(0, character.Glyph.Subrect.Left - 1);
                int top = Math.Max(0, character.Glyph.Subrect.Top - 1);
                int right = Math.Min(texW, character.Glyph.Subrect.Right + 1);
                int bottom = Math.Min(texH, character.Glyph.Subrect.Bottom + 1);
                int expandedW = right - left;
                int expandedH = bottom - top;

View on GitHub (pinned to 96fad776d2)