{"record":{"id":"17db7a160c72e170","repo":"siyuan-note/siyuan","slug":"parse-font-failed-w","errorCode":null,"errorMessage":"parse font failed: %w","messagePattern":"parse font failed: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"kernel/util/custom_font.go","lineNumber":334,"sourceCode":"func customFontHash(reader io.Reader) (string, error) {\n\thash := sha256.New()\n\tif _, err := io.Copy(hash, reader); err != nil {\n\t\treturn \"\", err\n\t}\n\treturn hex.EncodeToString(hash.Sum(nil)), nil\n}\n\nfunc parseCustomFontFile(fontFile *os.File) (ret *Font, err error) {\n\tdefer func() {\n\t\tif recovered := recover(); recovered != nil {\n\t\t\tret = nil\n\t\t\terr = fmt.Errorf(\"parse font failed: %v\", recovered)\n\t\t}\n\t}()\n\n\tparsed, err := sfnt.Parse(fontFile)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"parse font failed: %w\", err)\n\t}\n\tret, err = parseFontInfo(parsed)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"parse font metadata failed: %w\", err)\n\t}\n\treturn ret, nil\n}\n\nfunc validCustomFontID(id string) bool {\n\tif len(id) != sha256.Size*2 || strings.ToLower(id) != id {\n\t\treturn false\n\t}\n\tdecoded, err := hex.DecodeString(id)\n\treturn err == nil && len(decoded) == sha256.Size\n}\n\nfunc newCustomFont(id, fontPath string, font *Font) *CustomFont {\n\tweight := font.Weight","sourceCodeStart":316,"sourceCodeEnd":352,"githubUrl":"https://github.com/siyuan-note/siyuan/blob/9f775e8a12daef8255556097396f9b2739078892/kernel/util/custom_font.go#L316-L352","documentation":"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.","triggerScenarios":"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).","commonSituations":"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.","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"],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"font, _, err := util.InstallCustomFont(tempPath)\nvar cause error\nif err != nil && errors.As(err, &cause) {\n    log.Printf(\"font parse failed: %v\", cause) // inspect wrapped sfnt error\n}","preventionTips":["Verify checksums after downloading fonts","Use binary-safe transfer channels","Validate with fonttools/ttx before distribution"],"tags":["font-parsing","sfnt","corrupt-file"],"backgroundTag":"invalid-argument-format","analyzedSha":"9f775e8a12daef8255556097396f9b2739078892","analyzedAt":"2026-09-19T03:17:15.984Z","contentChangedAt":"2026-09-19T03:17:15.984Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}