helix-editor/helix · error · anyhow::Error
Expected 'inherits' to be a string: {}
Error message
Expected 'inherits' to be a string: {} What it means
Theme::load_theme reads each theme TOML and, if an 'inherits' key exists, requires it to be a string naming the parent theme; toml Values of other types (array, integer, boolean) fail with "Expected 'inherits' to be a string: {value}". The string is then resolved recursively — 'default' and 'base16_default' are built in, anything else loads from the themes directories, with cycle detection via visited_paths.
Source
Thrown at helix-view/src/theme.rs:154
/// Recursively load a theme, merging with any inherited parent themes.
///
/// The paths that have been visited in the inheritance hierarchy are tracked
/// to detect and avoid cycling.
///
/// It is possible for one file to inherit from another file with the same name
/// so long as the second file is in a themes directory with lower priority.
/// However, it is not recommended that users do this as it will make tracing
/// errors more difficult.
fn load_theme(&self, name: &str, visited_paths: &mut HashSet<PathBuf>) -> Result<Value> {
let path = self.path(name, visited_paths)?;
let theme_toml = self.load_toml(path)?;
let inherits = theme_toml.get("inherits");
let theme_toml = if let Some(parent_theme_name) = inherits {
let parent_theme_name = parent_theme_name.as_str().ok_or_else(|| {
anyhow!("Expected 'inherits' to be a string: {}", parent_theme_name)
})?;
let parent_theme_toml = match parent_theme_name {
// load default themes's toml from const.
"default" => DEFAULT_THEME_DATA.clone(),
"base16_default" => BASE16_DEFAULT_THEME_DATA.clone(),
_ => self.load_theme(parent_theme_name, visited_paths)?,
};
self.merge_themes(parent_theme_toml, theme_toml)
} else {
theme_toml
};
Ok(theme_toml)
}
pub fn read_names(path: &Path) -> Vec<String> {View on GitHub (pinned to 079a789e8c)
Solutions
- Make inherits a single string: inherits = "default".
- To layer multiple customizations, chain single-parent inherits (child inherits parent which inherits grandparent).
- Remove the inherits key entirely for a fully self-contained theme.
Example fix
# before (themes/mytheme.toml) inherits = ["default", "base16_default"] # after inherits = "default"
Defensive patterns
Strategy: validation
Validate before calling
fn inherits_is_string(toml: &toml::Value) -> Result<Option<&str>> {
match toml.get("inherits") {
None => Ok(None),
Some(v) => v.as_str().map(Some).ok_or_else(|| anyhow!(
"theme 'inherits' must be a single string, got: {v}"
)),
}
} Type guard
fn inherits_name(theme: &toml::Value) -> Option<&str> {
theme.get("inherits»).and_then(|v| v.as_str())
} Try / catch
let inherits = match theme_toml.get("inherits") {
Some(v) => Some(v.as_str().ok_or_else(|| anyhow!("theme {}: 'inherits' must be a string, got {v}", path.display()))?),
None => None,
}; Prevention
- Schema-check theme files (type of inherits must be string) before loading.
- One parent per theme; chain files for layering instead of arrays.
- Validate user themes at startup and report the file path with the bad key.
When it happens
Trigger: A theme file containing inherits = ["default"] (array), inherits = 1, or inherits = true; YAML-style or copy-paste artifacts around the value; also valid-string cases where the named parent cannot be found surface as the sibling path-resolution error instead.
Common situations: Users trying multiple inheritance by listing several parents (unsupported — one string only); machine-generated themes emitting non-string scalars; editing theme files in tooling that auto-quotes or converts values.
Related errors
- Failed to load config: {}
- Cycle found in inheriting: {}
- File not found for: {}
- Command not provided
- Incorrect transport {}
AI-assisted analysis of helix-editor/helix@079a789e8c (2026-08-16).
Data as JSON: /api/errors/8af22b1800cc6f9f.
Report an issue: GitHub.