d2lang/d2 · error
failed to encode ttf to woff: %v
Error message
failed to encode ttf to woff: %v
What it means
AddFontStyle stores the raw TTF in the FontFaces cache, then converts it to WOFF via fontlib.Sfnt2Woff for embedding as a base64 data URI. When the TTF bytes cannot be parsed/encoded as an SFNT font, it wraps and returns this error.
Source
Thrown at d2renderers/d2fonts/d2fonts_common.go:121
HandDrawn,
}
var FontFamiliesMu sync.Mutex
var FontEncodings syncmap.SyncMap[Font, string]
var FontFaces syncmap.SyncMap[Font, []byte]
var D2_FONT_TO_FAMILY = map[string]FontFamily{
"default": SourceSansPro,
"mono": SourceCodePro,
}
func AddFontStyle(font Font, style FontStyle, ttf []byte) error {
FontFaces.Set(font, ttf)
woff, err := fontlib.Sfnt2Woff(ttf)
if err != nil {
return fmt.Errorf("failed to encode ttf to woff: %v", err)
}
encodedWoff := fmt.Sprintf("data:application/font-woff;base64,%v", base64.StdEncoding.EncodeToString(woff))
FontEncodings.Set(font, encodedWoff)
return nil
}
func AddFontFamily(name string, regularTTF, italicTTF, boldTTF, semiboldTTF []byte) (*FontFamily, error) {
FontFamiliesMu.Lock()
defer FontFamiliesMu.Unlock()
customFontFamily := FontFamily(name)
regularFont := Font{
Family: customFontFamily,
Style: FONT_STYLE_REGULAR,
}
if regularTTF != nil {
err := AddFontStyle(regularFont, FONT_STYLE_REGULAR, regularTTF)View on GitHub (pinned to 0d69dca6f5)
Solutions
- Verify the font file is a real TTF (TrueType) file — check the first 4 bytes are 0x00010000 or 'true'/'OTTO' as supported
- Re-download/re-export the font; do not pass WOFF/WOFF2 files where TTF is expected
- Convert the font to plain TTF (e.g. with fonttools: ttx/flat conversion) before calling AddFontStyle
- Check the path/read call that produced the ttf []byte for empty or truncated content
Example fix
// before
d2fonts.AddFontStyle(font, style, readBytes("logo.woff"))
// after
ttfBytes := convertToTTF(readBytes("logo.woff")) // e.g. via fonttools
err := d2fonts.AddFontStyle(font, style, ttfBytes) Defensive patterns
Strategy: validation
Validate before calling
if len(ttf) < 4 {
return errors.New("font file too small to be a TTF")
}
tag := binary.BigEndian.Uint32(ttf[:4])
if tag != 0x00010000 && tag != 0x74727565 && tag != 0x4F54544F {
return errors.New("not a valid TTF/OTF file")
} Try / catch
if err := d2fonts.AddFontStyle(font, style, ttf); err != nil {
if strings.Contains(err.Error(), "failed to encode ttf to woff") {
// fall back to default font
}
} Prevention
- Ship fonts as true TTF files, never WOFF/WOFF2
- Validate magic bytes before registering fonts
- Check downloads for HTML error pages (404 bodies)
- Round-trip test custom fonts in CI
When it happens
Trigger: Calling d2fonts.AddFontStyle (or AddFontFamily, which delegates) with ttf bytes that are not a valid TTF/OTF (e.g. already-WOFF data, truncated download, HTML error page bytes).
Common situations: Loading a custom font whose file was corrupted or misnamed (.woff renamed to .ttf); downloading a font at runtime and getting a 404 HTML body; embedding a variable/font collection format Sfnt2Woff does not support.
Related errors
- expected .ttf file but %s has extension %s
- failed to read font at %s: %v
- "%v" is not a valid font in our system
- ruler does not have entire font family %s loaded, is a style
- ruler does not have entire mono font family %s loaded, is a
AI-assisted analysis of d2lang/d2@0d69dca6f5 (2026-08-31).
Data as JSON: /api/errors/872f2f99187ceb08.
Report an issue: GitHub.