siyuan-note/siyuan · error
parse font failed
Error message
parse font failed: %w
What it means
parseCustomFontFile calls sfnt.Parse to parse the font binary. This error is the normal (non-panic) parse-failure path: sfnt.Parse returned an error because the file, despite passing the 4-byte magic sniff, is not a structurally valid TrueType/OpenType font, and the cause is wrapped with %w so errors.Is/As work.
Solutions
- Re-download or re-export the font; verify integrity against a known checksum
- Validate locally with fonttools (ttx font.ttf) which reports the broken table
- Ensure any transfer used binary mode and completed fully
- Remove the broken file from the custom fonts directory if it cannot be repaired
Defensive patterns
Strategy: try-catch
Try / catch
font, _, err := util.InstallCustomFont(tempPath)
var cause error
if err != nil && errors.As(err, &cause) {
log.Printf("font parse failed: %v", cause) // inspect wrapped sfnt error
} Prevention
- Verify checksums after downloading fonts
- Use binary-safe transfer channels
- Validate with fonttools/ttx before distribution
When it happens
Trigger: Calling InstallCustomFont or loadCustomFontsLocked on a file with a valid TTF/OTF magic header but broken/missing required tables (e.g. truncated 'glyf'/'cff' data, bad offsets).
Common situations: Fonts truncated during download after the first 4 bytes; fonts corrupted by binary-unsafe transfer (e.g. text-mode FTP); hand-edited or subsetted files produced by buggy tooling.
Understand the failure class
Background: "Invalid ... format", "must be in format X", "does not look like a ..." — invalid argument format errors across CLI tools and libraries — this error's family across 17 libraries.
Related errors
- parse font failed
- parse font metadata failed
- decode image failed
- invalid marketplace package archive
- load block tree [ ] failed: tree is empty
AI-assisted analysis of siyuan-note/siyuan@9f775e8a12 (2026-09-19).
Data as JSON: /api/errors/17db7a160c72e170.
Report an issue: GitHub.
Appendix: source
Thrown at kernel/util/custom_font.go:334
func customFontHash(reader io.Reader) (string, error) {
hash := sha256.New()
if _, err := io.Copy(hash, reader); err != nil {
return "", err
}
return hex.EncodeToString(hash.Sum(nil)), nil
}
func parseCustomFontFile(fontFile *os.File) (ret *Font, err error) {
defer func() {
if recovered := recover(); recovered != nil {
ret = nil
err = fmt.Errorf("parse font failed: %v", recovered)
}
}()
parsed, err := sfnt.Parse(fontFile)
if err != nil {
return nil, fmt.Errorf("parse font failed: %w", err)
}
ret, err = parseFontInfo(parsed)
if err != nil {
return nil, fmt.Errorf("parse font metadata failed: %w", err)
}
return ret, nil
}
func validCustomFontID(id string) bool {
if len(id) != sha256.Size*2 || strings.ToLower(id) != id {
return false
}
decoded, err := hex.DecodeString(id)
return err == nil && len(decoded) == sha256.Size
}
func newCustomFont(id, fontPath string, font *Font) *CustomFont {
weight := font.WeightView on GitHub (pinned to 9f775e8a12)