stride3d/stride · error · InvalidOperationException
The specified DefaultCharacter is not part of this font.
Error message
The specified DefaultCharacter is not part of this font.
What it means
Stride's OfflineRasterizedSpriteFontCompiler rasterizes glyphs and requires a fallback glyph for characters missing from the font. After building the glyph list it checks that the asset's DefaultCharacter was actually rasterized; if not, it throws this InvalidOperationException. A default character that is not in the font would produce a null fallback glyph at render time, so the compiler fails fast during asset build.
Solutions
- Open the font asset and set DefaultCharacter to a character verified to exist in the font file ('?' or '*' are almost always present).
- If the font lacks a suitable default, switch to a font file with broader coverage (a full Unicode font).
- Alternatively set DefaultCharacter to null/0 so no default-glyph validation applies, if the pipeline allows it.
- Verify actual coverage with a font inspection tool (fontforge, OS character map) before setting the value.
Example fix
// before (font asset) <DefaultCharacter>é</DefaultCharacter> // after <DefaultCharacter>?</DefaultCharacter>
Defensive patterns
Strategy: validation
Validate before calling
// before compiling, confirm the default char exists in the font's cmap
if (asset.DefaultCharacter != default && !FontCoversCharacter(fontPath, asset.DefaultCharacter.Value))
asset.DefaultCharacter = '?'; // safe fallback present in nearly all fonts Type guard
bool IsValidDefaultCharacter(SpriteFontAsset asset) =>
asset.DefaultCharacter == default ||
FontCoversCharacter(asset.FontSource.GetFontPath(), asset.DefaultCharacter.Value); Try / catch
try
{
var glyphs = OfflineRasterizedFontCompiler.Compile(factory, asset);
}
catch (InvalidOperationException ex) when (ex.Message.Contains("DefaultCharacter"))
{
asset.DefaultCharacter = '?';
glyphs = OfflineRasterizedFontCompiler.Compile(factory, asset); // retry with safe default
} Prevention
- Pick a default character you verified exists in the font (ASCII '?' or '*' is safest).
- Keep DefaultCharacter and the CharacterSet/regions in sync — include the default in the compiled set.
- Add a pre-build asset check that validates DefaultCharacter against font coverage.
- Re-validate font assets after swapping the underlying .ttf/.otf file.
When it happens
Trigger: Calling ImportFont in OfflineRasterizedFontCompiler (directly or via Compile, which feeds GetCharactersToImport/ImportFont) with a SpriteFontAsset whose DefaultCharacter is a codepoint the font file does not contain — e.g. DefaultCharacter='é' on an ASCII-only TTF, or a character outside the compiled CharacterSet.
Common situations: Setting DefaultCharacter in a font asset to a symbol the TTF lacks; copying a font asset between projects where the new font has different coverage; specifying a default character excluded from the character regions/CharacterSet.
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
- Type [{0}] must be assignable to Asset or be a Package
- Cannot add an asset with an empty Id
- One of the asset does not match the directory hierarchy.
- Font file not found: {fontPath}
- Font file not found: {fontPath}
AI-assisted analysis of stride3d/stride@96fad776d2 (2026-09-14).
Data as JSON: /api/errors/5f83373fc72a3c2a.
Report an issue: GitHub.
Appendix: source
Thrown at sources/engine/Stride.Assets/SpriteFont/Compiler/OfflineRasterizedFontCompiler.cs:191
// Sort the glyphs
glyphs.Sort((left, right) => left.Character.CompareTo(right.Character));
// Check that the default character is part of the glyphs
if (options.DefaultCharacter != 0)
{
bool defaultCharacterFound = false;
foreach (var glyph in glyphs)
{
if (glyph.Character == options.DefaultCharacter)
{
defaultCharacterFound = true;
break;
}
}
if (!defaultCharacterFound)
{
throw new InvalidOperationException("The specified DefaultCharacter is not part of this font.");
}
}
return glyphs.ToArray();
}
public static List<char> GetCharactersToImport(SpriteFontAsset asset)
{
var characters = new List<char>();
var fontTypeStatic = asset.FontType as OfflineRasterizedSpriteFontType;
if (fontTypeStatic == null)
throw new ArgumentException("Tried to compile a dynamic sprite font with compiler for signed distance field fonts");
// extract the list from the provided file if it exits
if (File.Exists(fontTypeStatic.CharacterSet))
{
string text;View on GitHub (pinned to 96fad776d2)