AvaloniaUI/Avalonia · error · InvalidOperationException
No suitable cmap subtable found.
Error message
No suitable cmap subtable found.
What it means
A TrueType/OpenType font's 'cmap' table maps Unicode codepoints to glyph indices; without one, text cannot be rendered. GlyphTypeface.LoadCmap walks the table looking for Format 4 (BMP), then Format 13 (last-resort single-glyph), and if neither platform/encoding combination it prefers is present, it gives up. The exception signals the font is structurally valid but lacks any cmap subtable the engine can use.
Source
Thrown at src/Avalonia.Base/Media/Fonts/Tables/Cmap/CmapTable.cs:70
if (TryFindFormat12Or13Entry(entries, CmapFormat.Format12, out var format12Entry))
{
// Prefer Format 12 if available
return new CharacterToGlyphMap(new CmapFormat12Or13Table(format12Entry.GetSubtableMemory(table)));
}
// Then Format 4
if (TryFindFormat4Entry(entries, out var format4Entry))
{
return new CharacterToGlyphMap(new CmapFormat4Table(format4Entry.GetSubtableMemory(table)));
}
// Fallback to Format 13, which is a "last resort" format mapping many codepoints to a single glyph
if (TryFindFormat12Or13Entry(entries, CmapFormat.Format13, out var format13Entry))
{
return new CharacterToGlyphMap(new CmapFormat12Or13Table(format13Entry.GetSubtableMemory(table)));
}
throw new InvalidOperationException("No suitable cmap subtable found.");
// Tries to find the best Format 12 subtable entry based on platform and encoding preferences
static bool TryFindFormat12Or13Entry(CmapSubtableEntry[] entries, CmapFormat expectedFormat, out CmapSubtableEntry result)
{
result = default;
var foundPlatformScore = int.MaxValue;
var foundEncodingScore = int.MaxValue;
foreach (var entry in entries)
{
if (entry.Format != expectedFormat)
{
continue;
}
var platformScore = entry.Platform switch
{
PlatformID.Unicode => 0,View on GitHub (pinned to 11c5427268)
Solutions
- Validate the font with a tool (fontTools 'ttx -l', FontForge, or Microsoft Font Validator) and confirm it has a Format 4 subtable with platformID=3/encodingID=1 or a Format 12/13 subtable.
- Re-export or subset the font ensuring a Unicode BMP (3,1) Format 4 cmap subtable is included.
- Substitute a known-good system font (e.g. an installed Segoe UI / DejaVu Sans) to confirm the GlyphTypeface pipeline works, then bisect back to the failing asset.
- If loading untrusted user fonts, catch InvalidOperationException around GlyphTypeface construction and report the asset path rather than crashing.
Example fix
// before
var typeface = new GlyphTypeface(new Uri(assetUri));
// after
GlyphTypeface typeface;
try { typeface = new GlyphTypeface(new Uri(assetUri)); }
catch (InvalidOperationException ex) when (ex.Message.Contains("cmap"))
{
typeface = new GlyphTypeface(_fallbackSystemFontUri);
_logger.LogWarning("Asset {Uri} has no usable cmap; falling back. {Err}", assetUri, ex.Message);
} Defensive patterns
Strategy: fallback
Validate before calling
static bool HasUsableCmap(string fontPath)
{
try { using var gt = new GlyphTypeface(new Uri(fontPath)); return gt.GlyphCount > 0; }
catch (InvalidOperationException) { return false; }
} Try / catch
try { _typeface = new GlyphTypeface(uri); }
catch (InvalidOperationException ex) when (ex.Message.Contains("cmap"))
{
_typeface = new GlyphTypeface(_systemFallbackUri);
Log.AssetFontIncompatible(uri, ex.Message);
} Prevention
- Validate third-party font assets with Font Validator or fontTools before shipping.
- Keep a guaranteed-good system font as a fallback GlyphTypeface source.
- Treat any user-uploaded font as untrusted: probe with GlyphCount before use.
When it happens
Trigger: Calling GlyphTypeface on a font file whose cmap only contains Format 0, 1, 2, 6, or other unsupported encodings; a font with cmap entries whose platformID/encodingID do not match the preferred Windows/Unicode scores; a corrupt font whose cmap subtables fail to parse so the filter loop yields nothing.
Common situations: Shipping a legacy Mac-only TrueType font (platformID 1 only); embedding a hand-crafted or stripped font where the toolchain dropped the Unicode BMP (3,1) subtable; reading a CFF/CFF2 OTF that only declares a Format 12 (3,10) subtable but the loop's platform/encoding scoring rejects it; loading a non-font file as a font.
Related errors
- Could not load the '{TableName}' table.
- Default font family name can't be null or empty.
- '{FontFamily.DefaultFontFamilyName}' is a placeholder and ca
- No cmap table found.
- Stream is not readable
AI-assisted analysis of AvaloniaUI/Avalonia@11c5427268 (2026-08-13).
Data as JSON: /api/errors/4472cdb77304f25a.
Report an issue: GitHub.