stride3d/stride · error · FileNotFoundException
Font file not found
Error message
Font file not found: {filePath} What it means
RuntimeFontProvider.RegisterFont validates that the font file exists on disk before registering it, throwing FileNotFoundException with the offending path. This gives an early, clear failure instead of a deep FreeType error when the loader later cannot open the file.
Solutions
- Check the path exists before registering: File.Exists(filePath), and use absolute paths built from AppContext.BaseDirectory
- Ship the required fonts with your app and reference them via a content/root directory
- Guard platform-specific system font paths (e.g. use cross-platform font lookup instead of C:\Windows\Fonts)
- Catch FileNotFoundException around RegisterFont and fall back to a bundled default font
Example fix
// before
fontProvider.RegisterFont("MyFont", "fonts/MyFont.ttf");
// after
var path = Path.Combine(AppContext.BaseDirectory, "fonts", "MyFont.ttf");
if (!File.Exists(path)) throw new FileNotFoundException("Bundle missing font", path);
fontProvider.RegisterFont("MyFont", path); Defensive patterns
Strategy: validation
Validate before calling
var fullPath = Path.GetFullPath(filePath);
if (!File.Exists(fullPath))
throw new FileNotFoundException($"Font file missing: {fullPath}", fullPath); Try / catch
try { fontProvider.RegisterFont(name, path, style); }
catch (FileNotFoundException ex)
{
log.Warn($"Font {ex.FileName} missing; using fallback font");
fontProvider.RegisterFont(name, BundledFallbackFontPath, style);
} Prevention
- Resolve font paths relative to AppContext.BaseDirectory
- Include fonts in deployment artifacts and verify in post-build checks
- Avoid hard-coded OS font paths; bundle your own fonts
When it happens
Trigger: Calling RegisterFont(fontName, filePath, style) where File.Exists(filePath) is false: typo in path, wrong working directory, relative path resolved against an unexpected base, or the font not shipped with the app.
Common situations: Deploying without copying OS/custom font files; relative paths that break when the working directory differs (e.g. app run from a different folder); platform-specific font paths like C:\Windows\Fonts that don't exist on Linux/macOS.
Understand the failure class
Background: "File not found" and ENOENT errors: why libraries can't find a file that should exist — this error's family across 50 libraries.
Related errors
- Package file [ ] was not found
- Unable to find the file
- Could not find bundle
- Font file not found
- Font file not found
AI-assisted analysis of stride3d/stride@96fad776d2 (2026-09-14).
Data as JSON: /api/errors/0a459a76d4ec16f3.
Report an issue: GitHub.
Appendix: source
Thrown at sources/engine/Stride.Graphics/Font/RuntimeFontProvider.cs:52
/// </summary>
/// <remarks>
/// <para>Once registered, fonts are loaded into memory and cached for the lifetime of the font system.
/// Individual fonts cannot be unregistered or unloaded - they remain in memory until the application exits
/// or the font system is disposed.</para>
/// <para>Attempting to register the same font name and style with a different file path will throw an exception.</para>
/// </remarks>
/// <param name="fontName">The name to use when loading the font (e.g., "MyFont").</param>
/// <param name="filePath">The absolute or relative path to the .ttf file.</param>
/// <param name="style">The font style.</param>
/// <exception cref="ArgumentNullException">Thrown when <paramref name="fontName"/> is null or empty.</exception>
/// <exception cref="FileNotFoundException">Thrown when the font file does not exist.</exception>
/// <exception cref="InvalidOperationException">Thrown when attempting to register the same font name and style with a different file path.</exception>
public void RegisterFont(string fontName, string filePath, FontStyle style = FontStyle.Regular)
{
ArgumentException.ThrowIfNullOrWhiteSpace(fontName);
if (!File.Exists(filePath))
throw new FileNotFoundException($"Font file not found: {filePath}", filePath);
var key = FontHelper.GetFontPath(fontName, style);
if (registeredFonts.TryGetValue(key, out var existing))
{
if (existing.FilePath == filePath) return;
throw new InvalidOperationException(
$"Font '{fontName}' with style '{style}' is already registered with path '{existing.FilePath}'. " +
$"Cannot register a different path '{filePath}' for the same font name and style.");
}
fontSystem.FontManager.LoadFontFromFileSystem(fontName, filePath, style);
registeredFonts[key] = new RuntimeFontInfo(fontName, filePath, style);
}
/// <summary>View on GitHub (pinned to 96fad776d2)