stride3d/stride · error · InvalidOperationException

Failed to load font ' ' (FreeType error )

Error message

Failed to load font '{fontPath}' (FreeType error {err})

What it means

FreeTypeFontImporter.Import loads the font bytes with FT_New_Memory_Face; if FreeType returns a non-zero error code the importer throws this InvalidOperationException. It means FreeType could not parse the font data as a valid font face (the file existed but is invalid/unsupported).

Solutions

  1. Verify the font file is a valid, uncorrupted TTF/OTF (open it in a font viewer).
  2. Re-download or re-export the font file; avoid truncated copies.
  3. Try a different static font file; some variable/restricted fonts fail to load.
Defensive patterns

Strategy: validation

Validate before calling

var bytes = File.ReadAllBytes(fontPath);
if (bytes.Length < 4 ||
    !(bytes[0] == 0x00 && bytes[1] == 0x01 && bytes[2] == 0x00 && bytes[3] == 0x00) &&
    !System.Text.Encoding.ASCII.GetString(bytes, 0, 4).Contains("OTTO"))
    throw new InvalidDataException("Not a valid TTF/OTF file");

Try / catch

catch (InvalidOperationException ex) when (ex.Message.Contains("FreeType error")) { log.Error($"Invalid font data: {ex.Message}"); }

Prevention

When it happens

Trigger: Passing a corrupt, truncated, or non-font file (wrong format, DRM-protected font, HTML error page saved as .ttf) to FT_New_Memory_Face during sprite font compilation.

Common situations: Misnamed file extensions (e.g. an OTF variable font variant unsupported by the bundled FreeType); partial downloads; wrong file selected in the FontSource picker.

Understand the failure class

Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.

Related errors


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

Appendix: source

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

                throw new InvalidOperationException($"Failed to initialize FreeType library (error {err})");

            try
            {
                var fontPath = options.FontSource.GetFontPath();
                if (string.IsNullOrEmpty(fontPath) || !File.Exists(fontPath))
                    throw new FileNotFoundException($"Font file not found: {fontPath}");

                var fontData = File.ReadAllBytes(fontPath);
                var handle = GCHandle.Alloc(fontData, GCHandleType.Pinned);

                try
                {
                    FT_FaceRec* face;
                    fixed (byte* ptr = fontData)
                    {
                        err = FreeTypeNative.FT_New_Memory_Face(library, ptr, new CLong(fontData.Length), new CLong(0), out face);
                        if (err != 0)
                            throw new InvalidOperationException($"Failed to load font '{fontPath}' (FreeType error {err})");
                    }

                    try
                    {
                        var fontSize = options.FontType.Size;

                        // Set font size: 26.6 fixed-point, 72 dpi so size is in pixels
                        var charSize = new CLong((int)(fontSize * 64));
                        FreeTypeNative.FT_Set_Char_Size(face, charSize, charSize, 72, 72);

                        // Compute line spacing and baseline using FreeType metrics
                        // These are in font units — convert to pixels
                        float unitsToPixels = fontSize / face->units_per_EM;
                        var lineGap = (face->height - face->ascender + face->descender) * options.LineGapFactor;
                        LineSpacing = (lineGap + face->ascender - face->descender) * unitsToPixels;
                        BaseLine = (lineGap * options.LineGapBaseLineFactor + face->ascender) * unitsToPixels;

                        var glyphList = new List<Glyph>();

View on GitHub (pinned to 96fad776d2)