{"record":{"id":"872f2f99187ceb08","repo":"d2lang/d2","slug":"failed-to-encode-ttf-to-woff-v","errorCode":null,"errorMessage":"failed to encode ttf to woff: %v","messagePattern":"failed to encode ttf to woff: (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"d2renderers/d2fonts/d2fonts_common.go","lineNumber":121,"sourceCode":"\tHandDrawn,\n}\n\nvar FontFamiliesMu sync.Mutex\n\nvar FontEncodings syncmap.SyncMap[Font, string]\nvar FontFaces syncmap.SyncMap[Font, []byte]\n\nvar D2_FONT_TO_FAMILY = map[string]FontFamily{\n\t\"default\": SourceSansPro,\n\t\"mono\":    SourceCodePro,\n}\n\nfunc AddFontStyle(font Font, style FontStyle, ttf []byte) error {\n\tFontFaces.Set(font, ttf)\n\n\twoff, err := fontlib.Sfnt2Woff(ttf)\n\tif err != nil {\n\t\treturn fmt.Errorf(\"failed to encode ttf to woff: %v\", err)\n\t}\n\tencodedWoff := fmt.Sprintf(\"data:application/font-woff;base64,%v\", base64.StdEncoding.EncodeToString(woff))\n\tFontEncodings.Set(font, encodedWoff)\n\n\treturn nil\n}\n\nfunc AddFontFamily(name string, regularTTF, italicTTF, boldTTF, semiboldTTF []byte) (*FontFamily, error) {\n\tFontFamiliesMu.Lock()\n\tdefer FontFamiliesMu.Unlock()\n\tcustomFontFamily := FontFamily(name)\n\n\tregularFont := Font{\n\t\tFamily: customFontFamily,\n\t\tStyle:  FONT_STYLE_REGULAR,\n\t}\n\tif regularTTF != nil {\n\t\terr := AddFontStyle(regularFont, FONT_STYLE_REGULAR, regularTTF)","sourceCodeStart":103,"sourceCodeEnd":139,"githubUrl":"https://github.com/d2lang/d2/blob/0d69dca6f532ceaeacd615d35d1eaa41a238ffdb/d2renderers/d2fonts/d2fonts_common.go#L103-L139","documentation":"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.","triggerScenarios":"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).","commonSituations":"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.","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"],"exampleFix":"// before\nd2fonts.AddFontStyle(font, style, readBytes(\"logo.woff\"))\n// after\nttfBytes := convertToTTF(readBytes(\"logo.woff\")) // e.g. via fonttools\nerr := d2fonts.AddFontStyle(font, style, ttfBytes)","handlingStrategy":"validation","validationCode":"if len(ttf) < 4 {\n\treturn errors.New(\"font file too small to be a TTF\")\n}\ntag := binary.BigEndian.Uint32(ttf[:4])\nif tag != 0x00010000 && tag != 0x74727565 && tag != 0x4F54544F {\n\treturn errors.New(\"not a valid TTF/OTF file\")\n}","typeGuard":null,"tryCatchPattern":"if err := d2fonts.AddFontStyle(font, style, ttf); err != nil {\n\tif strings.Contains(err.Error(), \"failed to encode ttf to woff\") {\n\t\t// fall back to default font\n\t}\n}","preventionTips":["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"],"tags":["fonts","encoding","woff"],"backgroundTag":"invalid-font-file","analyzedSha":"0d69dca6f532ceaeacd615d35d1eaa41a238ffdb","analyzedAt":"2026-08-31T12:19:21.182Z","schemaVersion":2},"datasetVersion":"2026-08-31T14:17:45.589Z"}