helix-editor/helix · error · anyhow::Error
File not found for: {}
Error message
File not found for: {} What it means
While resolving a theme (or an 'inherits' parent), Helix's Loader searches every configured themes directory in priority order for <name>.toml. If no directory contains that file — and the name is not one of the two built-ins 'default' / 'base16_default', which are served from embedded data — path() returns None for every directory and the loader raises 'File not found for: {name}'. The name is matched exactly (case-sensitive) against the file stem, and the file must live inside a directory named themes/ with a .toml extension.
Source
Thrown at helix-view/src/theme.rs:247
.iter()
.find_map(|dir| {
let path = dir.join(&filename);
if !path.exists() {
None
} else if visited_paths.contains(&path) {
// Avoiding cycle, continuing to look in lower priority directories
cycle_found = true;
None
} else {
visited_paths.insert(path.clone());
Some(path)
}
})
.ok_or_else(|| {
if cycle_found {
anyhow!("Cycle found in inheriting: {}", name)
} else {
anyhow!("File not found for: {}", name)
}
})
}
pub fn default_theme(&self, true_color: bool) -> Theme {
if true_color {
self.default()
} else {
self.base16_default()
}
}
/// Returns the default theme
pub fn default(&self) -> Theme {
DEFAULT_THEME.clone()
}
/// Returns the alternative 16-color default themeView on GitHub (pinned to 079a789e8c)
Solutions
- Confirm the exact file: run ls ~/.config/helix/themes/ (and the runtime themes/ dir) and copy the file stem verbatim — e.g. theme = "monokai_pro_spectrum", not "MonokaiPro Spectrum".
- If the file is missing, move it into a themes/ subdirectory of the user config dir: ~/.config/helix/themes/<name>.toml (extension must be exactly .toml).
- For a broken inherits key, point it at a theme that exists, or at the always-available built-ins: inherits = "default" or inherits = "base16_default" (these are matched specially and never need a file).
- If the theme comes from a collection you meant to install, fetch it into the user themes directory (e.g. git clone the theme repo into ~/.config/helix/themes).
- As a library consumer, pre-check existence (see defense section) so a missing theme falls back to default_theme() instead of propagating the error.
Example fix
# before — ~/.config/helix/config.toml theme = "Monokai Pro" # after (file is ~/.config/helix/themes/monokai_pro.toml) theme = "monokai_pro"
Defensive patterns
Strategy: validation
Validate before calling
// Check resolvability before Loader::load using the same dirs
// you passed to Loader::new (highest priority first).
fn theme_file_exists(dirs: &[PathBuf], name: &str) -> bool {
if name == "default" || name == "base16_default" {
return true; // embedded built-ins, no file needed
}
dirs.iter()
.map(|d| d.join("themes").join(format!("{name}.toml")))
.any(|p| p.exists())
}
let theme_name = config.choose(mode);
if !theme_file_exists(&dirs, theme_name) {
// fall back instead of letting Loader::load fail
return Ok(loader.default_theme(true_color));
} Type guard
fn is_loadable_theme(dirs: &[PathBuf], name: &str) -> bool {
theme_file_exists(dirs, name)
} Try / catch
// anyhow errors are untyped here, so match on the message prefix:
match loader.load(theme_name) {
Ok(theme) => theme,
Err(err) if err.to_string().starts_with("File not found for") => {
log::warn!("theme '{theme_name}' not installed, using default");
loader.default_theme(true_color)
}
Err(err) => return Err(err),
} Prevention
- Copy theme names from the actual file listing (ls ~/.config/helix/themes/), never from screenshots or docs — stems are matched case-sensitively with underscores, not spaces.
- Custom themes go in the themes/ subdirectory of the config dir and must end in exactly .toml; beware editors that save file.toml.toml.
- For inherits, prefer the always-present built-ins ("default", "base16_default") as roots of your chain.
- After upgrading Helix, re-check theme = in config.toml against the shipped theme list (:theme followed by Tab completes available names).
- When loading user-specified theme names programmatically, always validate existence first and keep default_theme() as the fallback path.
When it happens
Trigger: Calling Loader::load("nope") when no themes/nope.toml exists in any theme dir; setting theme = "Monokai Pro" in config.toml (spaces/case don't match monokai_pro.toml); a theme file with inherits = "solarized" when only solarized-dark.toml exists; placing the file at ~/.config/helix/mytheme.toml instead of ~/.config/helix/themes/mytheme.toml; naming it mytheme.txt or mytheme.toml.toml so the stem mismatch fails lookup.
Common situations: Typos or wrong casing in the theme= setting of config.toml; referencing a theme that was renamed or removed in a newer Helix release; themes distributed as plugins that the user forgot to install; an inherits key naming a theme only present on another machine; file saved with a hidden double extension by editors that append .toml again.
Related errors
- Expected 'inherits' to be a string: {}
- Cycle found in inheriting: {}
- Failed to load config: {}
- Could not load theme: {}
- Command not provided
AI-assisted analysis of helix-editor/helix@079a789e8c (2026-08-16).
Data as JSON: /api/errors/e4356887cb50d033.
Report an issue: GitHub.