AvaloniaUI/Avalonia · error · InvalidOperationException
'{FontFamily.DefaultFontFamilyName}' is a placeholder and ca
Error message
'{FontFamily.DefaultFontFamilyName}' is a placeholder and cannot be used as the default font family name. Provide a concrete font family name via {nameof(FontManagerOptions)} or the platform implementation. What it means
GetDefaultFontFamilyName throws InvalidOperationException when the resolved default font family name equals the placeholder constant FontFamily.DefaultFontFamilyName (which is "$Default"). "$Default" is a sentinel meaning 'use the system default'; using it as the concrete default would cause infinite recursion/unresolved resolution, so it is explicitly rejected. A real font name must be supplied via FontManagerOptions or the platform.
Source
Thrown at src/Avalonia.Base/Media/FontManager.cs:456
private string GetDefaultFontFamilyName(FontManagerOptions? options)
{
var defaultFontFamilyName = options?.DefaultFamilyName
?? PlatformImpl.GetDefaultFontFamilyName();
if (string.IsNullOrEmpty(defaultFontFamilyName) && SystemFonts.Count > 0)
{
defaultFontFamilyName = SystemFonts[0].Name;
}
if (string.IsNullOrEmpty(defaultFontFamilyName))
{
throw new InvalidOperationException(
"Default font family name can't be null or empty.");
}
if (defaultFontFamilyName == FontFamily.DefaultFontFamilyName)
{
throw new InvalidOperationException(
$"'{FontFamily.DefaultFontFamilyName}' is a placeholder and cannot be used as the default font family name. Provide a concrete font family name via {nameof(FontManagerOptions)} or the platform implementation.");
}
return defaultFontFamilyName;
}
void IDisposable.Dispose()
{
foreach (var pair in _fontCollections)
pair.Value.Dispose();
_fontCollections.Clear();
(PlatformImpl as IDisposable)?.Dispose();
}
}
}
View on GitHub (pinned to 11c5427268)
Solutions
- Set FontManagerOptions.DefaultFamilyName to a concrete, installed font family name (e.g. "Segoe UI", "Inter", "DejaVu Sans").
- Leave DefaultFamilyName null so the platform impl and SystemFonts fallback resolve a real font.
- Never use "$Default" (FontFamily.DefaultFontFamilyName) as the options value.
Example fix
// before
services.AddSingleton<FontManagerOptions>(_ => new FontManagerOptions
{
DefaultFamilyName = FontFamily.DefaultFontFamilyName // "$Default"
});
// after
services.AddSingleton<FontManagerOptions>(_ => new FontManagerOptions
{
DefaultFamilyName = "Inter"
}); Defensive patterns
Strategy: validation
Validate before calling
if (defaultFamilyName == FontFamily.DefaultFontFamilyName) // "$Default"
defaultFamilyName = "Inter"; // concrete fallback
var opts = new FontManagerOptions { DefaultFamilyName = defaultFamilyName }; Prevention
- Never set DefaultFamilyName to FontFamily.DefaultFontFamilyName ("$Default").
- Leave it null to let the platform/SystemFonts resolve, or set a concrete name.
- Add a startup guard that rejects the placeholder in config.
When it happens
Trigger: FontManagerOptions.DefaultFamilyName (or the platform implementation) returns the literal string "$Default". This happens when config or a binding forwards the sentinel placeholder instead of a concrete family name.
Common situations: Setting DefaultFamilyName = FontFamily.DefaultFontFamilyName in options (thinking it means 'default'). A platform impl incorrectly returning the sentinel. Copying a XAML/theme value that used the placeholder into the options.
Related errors
- Default font family name can't be null or empty.
- Font collection Key should follow the fonts: scheme.
- Animator has no property specified.
- Animator has no property specified.
- Animator has no property specified.
AI-assisted analysis of AvaloniaUI/Avalonia@11c5427268 (2026-08-13).
Data as JSON: /api/errors/affed7464235cc97.
Report an issue: GitHub.