siyuan-note/siyuan · error

invalid custom font ID

Error message

invalid custom font ID

What it means

Returned by RemoveCustomFont when the supplied id fails validCustomFontID. A valid ID is exactly 64 lowercase hex characters (sha256.Size*2) that hex-decode to 32 bytes — i.e. the sha256 hash produced at install time. Anything else is rejected before touching the font directory.

Source

Thrown at kernel/util/custom_font.go:169

	} else if !os.IsNotExist(statErr) {
		return nil, false, statErr
	}

	if err = os.Rename(tempPath, targetPath); err != nil {
		return nil, false, err
	}
	if err = os.Chmod(targetPath, 0644); err != nil {
		_ = os.Remove(targetPath)
		return nil, false, err
	}

	customFontsLoaded = false
	return newCustomFont(id, targetPath, font), true, nil
}

func RemoveCustomFont(id string) (*CustomFont, error) {
	if !validCustomFontID(id) {
		return nil, errors.New("invalid custom font ID")
	}

	customFontsLock.Lock()
	defer customFontsLock.Unlock()

	loadCustomFontsLocked()
	for _, font := range customFonts {
		if font.ID != id {
			continue
		}
		if err := os.Remove(font.path); err != nil {
			return nil, err
		}
		customFontsLoaded = false
		return cloneCustomFont(font), nil
	}
	return nil, os.ErrNotExist
}

View on GitHub (pinned to 251596fc0d)

Solutions

  1. Pass the exact CustomFont.ID returned by LoadCustomFonts (64-char lowercase hex), not the family/display name or URL.
  2. Strip any '/custom-fonts/' prefix or file extension before calling RemoveCustomFont.
  3. If the client only has a display name, resolve it to an ID via LoadCustomFonts first.

Example fix

// before
util.RemoveCustomFont(displayName)

// after
var id string
for _, f := range util.LoadCustomFonts() {
    if f.DisplayName == displayName {
        id = f.ID
        break
    }
}
if id == "" {
    return errors.New("font not found")
}
util.RemoveCustomFont(id)
Defensive patterns

Strategy: validation

Validate before calling

var fontIDRE = regexp.MustCompile(`^[0-9a-f]{64}$`)
func isValidFontID(id string) bool { return fontIDRE.MatchString(id) }

Prevention

When it happens

Trigger: Calling util.RemoveCustomFont(id) (or the matching kernel API) with an id that is the wrong length, contains uppercase letters or non-hex characters, or is otherwise not a sha256 hex digest.

Common situations: A client passed the font family name, display name, URL slug, or an index instead of the ID; the ID was truncated or had a leading '/custom-fonts/' prefix appended; a stale client from before IDs were introduced.

Related errors


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