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

  1. Check the path exists before registering: File.Exists(filePath), and use absolute paths built from AppContext.BaseDirectory
  2. Ship the required fonts with your app and reference them via a content/root directory
  3. Guard platform-specific system font paths (e.g. use cross-platform font lookup instead of C:\Windows\Fonts)
  4. 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

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


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)