stride3d/stride · error · InvalidOperationException

Failed to render glyph for character

Error message

Failed to render glyph for character '{character}' (FreeType error {err})

What it means

After loading, FT_Render_Glyph rasterizes the glyph outline at the requested anti-alias mode; a non-zero FreeType error causes this InvalidOperationException. Loading succeeded, but rendering the glyph bitmap failed.

Solutions

  1. Switch the font asset's anti-alias mode between Aliased and Normal to change the render mode.
  2. Exclude the failing characters from the font's character set.
  3. Use a plain outline TTF/OTF font instead of a bitmap-embedded/symbol font.
Defensive patterns

Strategy: try-catch

Try / catch

try
{
    importer.ImportGlyph(character, glyphIndex);
}
catch (InvalidOperationException ex) when (ex.Message.StartsWith("Failed to render glyph"))
{
    log.Warn($"Skipping unrenderable character '{character}'");
}

Prevention

When it happens

Trigger: FT_Render_Glyph returns an error for a character during offline font rasterization, usually when the loaded glyph has no outline (e.g. bitmap-only glyphs rendered in Normal mode) or face state is invalid.

Common situations: Symbol/bitmap-embedded fonts (EBDT/EBLC) whose glyphs cannot be rasterized in outline mode; mismatch between load target and render mode for special fonts.

Understand the failure class

Background: "This is a bug, please report it": internal invariant violations, unreachable panics, and SNH errors explained — this error's family across 47 libraries.

Related errors


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

Appendix: source

Thrown at sources/engine/Stride.Assets/SpriteFont/Compiler/FreeTypeFontImporter.cs:132

                };
                return glyph;
            }

            // Load and render the glyph
            {
                var loadTarget = antiAliasMode == FontAntiAliasMode.Aliased
                    ? FreeTypeLoadTarget.Mono
                    : FreeTypeLoadTarget.Normal;
                int err = FreeTypeNative.FT_Load_Glyph(face, glyphIndex, (int)FreeTypeLoadFlags.Default | (int)loadTarget);
                if (err != 0)
                    throw new InvalidOperationException($"Failed to load glyph for character '{character}' (FreeType error {err})");

                var renderMode = antiAliasMode == FontAntiAliasMode.Aliased
                    ? FreeTypeRenderMode.Mono
                    : FreeTypeRenderMode.Normal;
                err = FreeTypeNative.FT_Render_Glyph(face->glyph, renderMode);
                if (err != 0)
                    throw new InvalidOperationException($"Failed to render glyph for character '{character}' (FreeType error {err})");
            }

            ref FT_Bitmap ftBitmap = ref face->glyph->bitmap;
            int width = (int)ftBitmap.width;
            int height = (int)ftBitmap.rows;

            if (width == 0 || height == 0)
            {
                var emptyBitmap = new Image<Rgba32>(1, 1);
                return new Glyph(character, emptyBitmap)
                {
                    XOffset = face->glyph->bitmap_left,
                    YOffset = -face->glyph->bitmap_top,
                    XAdvance = face->glyph->advance.x.Value / 64.0f,
                };
            }

            var bitmap = new Image<Rgba32>(width, height);

View on GitHub (pinned to 96fad776d2)