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, err

View on GitHub (pinned to 251596fc0d)

Solutions

  1. Verify the upload actually wrote bytes to the temp file before calling InstallCustomFont (check the upload handler writes the full request body).
  2. Confirm tempPath was created by CreateCustomFontTemp and points at a file under CustomFontDir(), not a directory or symlink.
  3. 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

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


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