siyuan-note/siyuan · error

theme [%s] not exists or not available for dark mode

Error message

theme [%s] not exists or not available for dark mode

What it means

Returned by SetTheme when modes contains 1 (dark) but the requested theme name is not in Conf.Appearance.DarkThemes. Dark themes are loaded by LoadThemes into the DarkThemes slice; SetTheme checks membership by Name before assigning Conf.Appearance.ThemeDark.

Source

Thrown at kernel/model/appearance.go:96

	Conf.Appearance.Icon = icon
	return nil
}

func SetTheme(theme string, modes []int, appearanceMode string) error {
	Conf.m.Lock()
	defer Conf.m.Unlock()

	if theme != "" {
		for _, mode := range modes {
			switch mode {
			case 0:
				if !containTheme(theme, Conf.Appearance.LightThemes) {
					return fmt.Errorf("theme [%s] not exists or not available for light mode", theme)
				}
				Conf.Appearance.ThemeLight = theme
			case 1:
				if !containTheme(theme, Conf.Appearance.DarkThemes) {
					return fmt.Errorf("theme [%s] not exists or not available for dark mode", theme)
				}
				Conf.Appearance.ThemeDark = theme
			}
		}
	}

	if appearanceMode != "" {
		switch appearanceMode {
		case "light":
			Conf.Appearance.ModeOS = false
			Conf.Appearance.Mode = 0
		case "dark":
			Conf.Appearance.ModeOS = false
			Conf.Appearance.Mode = 1
		case "system":
			Conf.Appearance.ModeOS = true
		default:
			return fmt.Errorf("invalid appearance mode: %s", appearanceMode)

View on GitHub (pinned to 251596fc0d)

Solutions

  1. Install the theme pack, or choose a name from Conf.Appearance.DarkThemes (default "midnight").
  2. If the theme is light-only, do not include mode 1 in the modes slice for that call.
  3. Call SetTheme only after InitAppearance has loaded themes.

Example fix

// before
model.SetTheme("light-only-theme", []int{0, 1}, "")
// after
model.SetTheme("midnight", []int{1}, "")
Defensive patterns

Strategy: validation

Validate before calling

if !containTheme(name, Conf.Appearance.DarkThemes) {
    return fmt.Errorf("theme %q not installed for dark mode", name)
}

Type guard

func themeAvailableForMode(name string, themes []*conf.AppearanceTheme) bool {
    for _, t := range themes { if t.Name == name { return true } }
    return false
}

Prevention

When it happens

Trigger: Calling SetTheme with mode 1 and a theme not present among installed dark themes — uninstalled theme, typo, or a light-only theme passed for dark mode.

Common situations: A theme pack was uninstalled but config still references it; a theme is light-only and is passed for dark mode; calling before LoadThemes has run.

Related errors


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