yorukot/superfile · error

could not read user's theme file(%s), err : %w

Error message

could not read user's theme file(%s), err : %w

What it means

LoadUserTheme reads a user theme file from disk and wraps any os.ReadFile failure with this message. It is thrown when the theme file cannot be read at all (as opposed to failing to parse). The wrapped error (%w) contains the underlying os error such as ENOENT or EACCES.

Source

Thrown at src/internal/common/load_config.go:215

			utils.PrintfAndExitf("Unexpected error while reading default theme file : %v. Exiting...", err)
		}
	}

	// Validations
	if len(Theme.GradientColor) != RequiredGradientColorCount {
		utils.PrintlnAndExit(
			LoadThemeError(
				"gradient_color",
				"Gradient color must contain exactly two values.",
			),
		)
	}
}

func LoadUserTheme(themeFile string, obj *ThemeType) error {
	data, err := os.ReadFile(themeFile)
	if err != nil {
		return fmt.Errorf("could not read user's theme file(%s), err : %w", themeFile, err)
	}
	if err = toml.Unmarshal(data, obj); err != nil {
		return fmt.Errorf("could not unmarshal user's theme file(%s) : %w", themeFile, err)
	}
	return nil
}

// LoadAllDefaultConfig : Load all default configurations from embedded superfile_config folder into global
// configurations variables and write theme files if its needed.
func LoadAllDefaultConfig(content embed.FS) {
	err := LoadConfigStringGlobals(content)
	if err != nil {
		slog.Error("Could not load default config from embed FS", "error", err)
		return
	}

	currentThemeVersion, err := os.ReadFile(variable.ThemeFileVersion)
	if err != nil && !os.IsNotExist(err) {

View on GitHub (pinned to b72f550bc6)

Solutions

  1. Check that the theme file path printed in the error actually exists (ls the path).
  2. Set the theme in config to a name matching an existing file in the themes directory, or create the file.
  3. Fix file permissions (chmod 644) or ownership on the theme file.
  4. Verify the path is a regular file, not a directory.

Example fix

// before
theme = 'my-custom-theme' // file never created
// after
theme = 'catppuccin' // matches ~/.config/superfile/theme/catppuccin.toml
Defensive patterns

Strategy: validation

Validate before calling

if st, err := os.Stat(themeFile); err != nil {
    return fmt.Errorf("theme file %q not accessible: %w", themeFile, err)
} else if st.IsDir() {
    return fmt.Errorf("theme path %q is a directory", themeFile)
}

Type guard

func themeFileReadable(path string) bool {
    f, err := os.Open(path)
    if err != nil { return false }
    f.Close()
    return true
}

Try / catch

if err := common.LoadUserTheme(themeFile, &theme); err != nil {
    var pErr *fs.PathError
    if errors.As(err, &pErr) && errors.Is(pErr.Err, fs.ErrNotExist) {
        log.Warnf("theme %q missing, using default", themeFile)
        return common.LoadDefaultTheme()
    }
    return err
}

Prevention

When it happens

Trigger: LoadThemeFile calls LoadUserTheme(themeFile, obj) and os.ReadFile(themeFile) returns an error: the file does not exist, permission is denied, or the path is a directory.

Common situations: User set a custom theme name in config but never created the corresponding ~/.config/superfile/theme/<name>.toml file; a typo in the theme path; file deleted or moved by another tool; restrictive file permissions after a dotfiles sync.

Understand the failure class

Background: "File not found" and ENOENT errors: why libraries can't find a file that should exist — this error's family across 50 libraries.

Related errors


AI-assisted analysis of yorukot/superfile@b72f550bc6 (2026-09-01). Data as JSON: /api/errors/83707345abecc3f0. Report an issue: GitHub.