siyuan-note/siyuan · error
parse font failed: %w
Error message
parse font failed: %w
What it means
Returned by parseCustomFontFile when sfnt.Parse returns a non-nil error (without panicking). Unlike the panic branch (errorIndex 1089), this is the normal error path: the parser recognized the input as invalid and returned an error, which is wrapped with %w so the underlying cause is preserved for errors.Is/As.
Source
Thrown at kernel/util/custom_font.go:329
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 251596fc0d)
Solutions
- Inspect the wrapped error (errors.Unwrap or %w chain) to see the specific sfnt parse failure, then address that cause.
- Replace the font from a known-good source.
- Validate with fonttools/ttx to confirm the table structure before re-uploading.
Example fix
// before
if _, _, err := util.InstallCustomFont(tempPath); err != nil {
log.Println(err)
}
// after
if _, _, err := util.InstallCustomFont(tempPath); err != nil {
var parseErr *sfnt.ParseError // if the underlying type is exposed
if errors.As(err, &parseErr) {
log.Printf("sfnt parse failure: %v", parseErr)
}
} Defensive patterns
Strategy: try-catch
Try / catch
if _, _, err := util.InstallCustomFont(tempPath); err != nil {
var inner = err
for errors.Unwrap(inner) != nil { inner = errors.Unwrap(inner) }
// inner now holds the underlying sfnt.Parse cause; branch on it
} Prevention
- Unwrap these errors to find the real sfnt cause before acting.
- Keep a known-good source for each custom font so a corrupt copy can be replaced.
When it happens
Trigger: InstallCustomFont or loadCustomFontsLocked passes a file whose header looks like TTF/OTF but whose internal structure (offset table, table directory, required tables) is invalid, so sfnt.Parse rejects it.
Common situations: A partially downloaded or truncated font (correct header, missing tables); a file that was concatenated or patched; an OTF whose CFF data is malformed.
Related errors
- parse font failed: %v
- parse font metadata failed: %w
- font file is invalid
- only TTF and OTF font files are supported
- font family is empty
AI-assisted analysis of siyuan-note/siyuan@251596fc0d (2026-08-12).
Data as JSON: /api/errors/17db7a160c72e170.
Report an issue: GitHub.