stride3d/stride · critical · InvalidOperationException
Failed to initialize FreeType library
Error message
Failed to initialize FreeType library (error {err}) What it means
The FontManager constructor calls FT_Init_FreeType and throws InvalidOperationException when FreeType returns a nonzero error code. This means the native FreeType library loaded but its global initialization failed, so no font work can be done in this process.
Solutions
- Verify the correct native freetype library for the platform/CPU is deployed next to the app (NativeLibraryHelper.PreloadLibrary resolves it)
- Re-copy or reinstall the Stride native dependencies so the freetype binary is not corrupted
- Check available memory; FreeType init allocates internal state and fails under memory pressure
- Log the numeric FreeType error code and compare with FreeType docs (FT_Err_*) to identify the cause
Defensive patterns
Strategy: try-catch
Validate before calling
// Cannot pre-validate native init; ensure native libs deployed: // verify 'freetype' native binary exists for the current RuntimeInformation.ProcessArchitecture
Try / catch
try { var fm = new FontManager(fileProvider); }
catch (InvalidOperationException ex) when (ex.Message.Contains("FreeType"))
{
log.Fatal("FreeType init failed; check native freetype deployment", ex);
throw;
} Prevention
- Deploy all Stride native dependencies per-platform and verify after build
- Test font initialization in CI containers to catch missing native libs early
- Monitor memory; FreeType init fails under severe memory pressure
When it happens
Trigger: Creating a new FontManager (directly or via FontSystem.Load) on a machine where FT_Init_FreeType fails, usually due to a broken/mismatched native freetype binary or exhausted memory.
Common situations: Missing or wrong-architecture native freetype.dll/libfreetype.so after deploying without the native assets; corrupted native library; low-memory environments (CI containers) where FreeType cannot allocate its internal structures.
Related errors
- Failed to initialize FreeType library
- Failed to initialize msdfgen context
- Failed to initialize the audio native layer.
- Failed to create Celt custom mode.
- Failed to create an instance of the celt encoder/decoder.
AI-assisted analysis of stride3d/stride@96fad776d2 (2026-09-14).
Data as JSON: /api/errors/e33586f9146222d8.
Report an issue: GitHub.
Appendix: source
Thrown at sources/engine/Stride.Graphics/Font/FontManager.cs:95
/// Note that we cannot just increase space taken in the bin packer because artifacts with old/previous characters may happen.
/// </remarks>
/// </summary>
private Int2 borderSize = Int2.One;
/// <summary>
/// Create an empty register.
/// </summary>
public FontManager(IDatabaseFileProviderService fileProviderService)
{
contentManager = new ContentManager(fileProviderService);
// Preload proper freetype native library (depending on CPU type).
NativeLibraryHelper.PreloadLibrary("freetype", typeof(FontManager));
// Initialize FreeType library
int err = FreeTypeNative.FT_Init_FreeType(out freetypeLibrary);
if (err != 0)
throw new InvalidOperationException($"Failed to initialize FreeType library (error {err})");
// launch the thumbnail builder thread
bitmapBuilderThread = new Thread(SafeAction.Wrap(BuildBitmapThread)) { IsBackground = true, Name = "Bitmap Builder thread" };
bitmapBuilderThread.Start();
}
/// <summary>
/// Start the generation of the specified character's bitmap.
/// </summary>
/// <remarks>Does nothing if the bitmap already exists or its generation is already pending.</remarks>
/// <param name="characterSpecification">The character we want the bitmap of</param>
/// <param name="synchronously">Indicate if the generation of the bitmap must by done synchronously or asynchronously</param>
public void GenerateBitmap(CharacterSpecification characterSpecification, bool synchronously)
{
// Synchronous: render glyph info and bitmap immediately on the calling thread.
// Hold dataStructuresLock so we never render the same glyph concurrently with the
// builder thread (whichever takes the lock first renders it, the other skips), which
// keeps ResetGlyph from clobbering freshly written glyph data.View on GitHub (pinned to 96fad776d2)