siyuan-note/siyuan · error
font file is empty
Error message
font file is empty
What it means
Returned by InstallCustomFont when os.Stat reports the temp file is not a regular file, or has a size below 1 byte. The check guards against empty or non-file uploads before any font parsing. The temp file comes from CreateCustomFontTemp, which writes into the custom-fonts directory.
Source
Thrown at kernel/util/custom_font.go:103
func LoadCustomFonts() []*CustomFont {
customFontsLock.Lock()
defer customFontsLock.Unlock()
loadCustomFontsLocked()
return cloneCustomFonts(customFonts)
}
func InstallCustomFont(tempPath string) (*CustomFont, bool, error) {
customFontsLock.Lock()
defer customFontsLock.Unlock()
info, err := os.Stat(tempPath)
if err != nil {
return nil, false, err
}
if !info.Mode().IsRegular() || info.Size() < 1 {
return nil, false, errors.New("font file is empty")
}
if MaxCustomFontSize < info.Size() {
return nil, false, errors.New("font file is too large")
}
fontFile, err := os.Open(tempPath)
if err != nil {
return nil, false, err
}
extension, err := detectCustomFontExtension(fontFile)
if err != nil {
fontFile.Close()
return nil, false, err
}
if _, err = fontFile.Seek(0, io.SeekStart); err != nil {
fontFile.Close()
return nil, false, errView on GitHub (pinned to 251596fc0d)
Solutions
- Verify the upload actually wrote bytes to the temp file before calling InstallCustomFont (check the upload handler writes the full request body).
- Confirm tempPath was created by CreateCustomFontTemp and points at a file under CustomFontDir(), not a directory or symlink.
- Re-run the font upload from the start so a fresh temp file is allocated and filled.
Example fix
// before
font, _, err := util.InstallCustomFont(tempPath)
// after
if info, serr := os.Stat(tempPath); serr != nil || !info.Mode().IsRegular() || info.Size() < 1 {
return errors.New("upload produced an empty file")
}
font, _, err := util.InstallCustomFont(tempPath) Defensive patterns
Strategy: validation
Validate before calling
func validFontUpload(tempPath string) error {
info, err := os.Stat(tempPath)
if err != nil { return err }
if !info.Mode().IsRegular() || info.Size() < 1 {
return errors.New("upload produced an empty file")
}
return nil
} Prevention
- Verify the upload handler writes the full request body and closes the temp file before handing the path off.
- Stat the temp file at the API boundary so empty uploads are rejected with a clear message.
When it happens
Trigger: Calling util.InstallCustomFont(tempPath) where tempPath points to an empty file (0 bytes), a directory, a device/socket, a symlink to nothing, or any non-regular file.
Common situations: The upload was interrupted so the temp file ended up empty; the frontend created the temp file but never streamed body bytes into it; a previous DiscardCustomFontTemp left a zero-byte file behind; the temp path points at a directory by mistake.
Related errors
- font file is too large
- font file is invalid
- no file found
- import path is not sub path of import dir
- field [file] or [url] must not be empty
AI-assisted analysis of siyuan-note/siyuan@251596fc0d (2026-08-12).
Data as JSON: /api/errors/825872f5f09b05fd.
Report an issue: GitHub.