siyuan-note/siyuan · error

parse font metadata failed: %w

Error message

parse font metadata failed: %w

What it means

Returned by parseCustomFontFile when parseFontInfo (font.go) fails after sfnt.Parse succeeded. The wrapped cause is typically 'font family is empty' (errorIndex 1092) — i.e. the font's name table has no usable Family entry — or a name-table read error. The %w wrap preserves the underlying error.

Source

Thrown at kernel/util/custom_font.go:333

	}
	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.Weight
	if weight < 1 || 1000 < weight {
		weight = 400
	}
	return &CustomFont{

View on GitHub (pinned to 251596fc0d)

Solutions

  1. Unwrap the error to confirm the cause — if it is 'font family is empty', the font is missing a usable Family name.
  2. Re-export the font with a valid Family name (nameID 1 or 16) using fonttools or FontForge.
  3. Use the original un-subsetted font instead of a stripped variant.
Defensive patterns

Strategy: try-catch

Try / catch

if _, _, err := util.InstallCustomFont(tempPath); err != nil {
    if strings.Contains(err.Error(), "parse font metadata failed") {
        // font is missing a usable name table — request a non-subsetted copy
    }
}

Prevention

When it happens

Trigger: InstallCustomFont or loadCustomFontsLocked passes a font that parses structurally but whose name table cannot be read or yields no family name (family empty or starting with '.').

Common situations: A stripped or subsetted font whose name table was removed to save space; a font with only non-Latin name entries that the selection logic skips; a font whose only family name begins with '.' (some legacy Mac fonts).

Related errors


AI-assisted analysis of siyuan-note/siyuan@251596fc0d (2026-08-12). Data as JSON: /api/errors/dd60bef599d1dda4. Report an issue: GitHub.