atuinsh/atuin · warning · std::io::Error
Parent requested but we hit the recursion limit
Error message
Parent requested but we hit the recursion limit
What it means
Thrown by ThemeManager::load_theme_from_config when a theme declares theme.parent but the recursion budget max_depth has hit 0. Depth starts at DEFAULT_MAX_DEPTH (10, theme.rs:12) and each parent hop calls load_theme with max_depth - 1, so any inheritance chain longer than 10, or a cycle (a parent of b, b parent of a), exhausts the budget. It is an io::ErrorKind::InvalidInput; via ThemeManager::load_theme it is caught and falls back to '(none)'.
Source
Thrown at crates/atuin-client/src/theme.rs:476
Err(e) => {
return Err(Box::new(Error::new(
ErrorKind::InvalidInput,
format!(
"Failed to deserialize theme: {}",
if debug {
e.to_string()
} else {
"set theme debug on for more info".to_string()
}
),
)));
}
};
let colors: HashMap<Meaning, String> = theme_config.colors;
let parent: Option<&Theme> = match theme_config.theme.parent {
Some(parent_name) => {
if max_depth == 0 {
return Err(Box::new(Error::new(
ErrorKind::InvalidInput,
"Parent requested but we hit the recursion limit",
)));
}
Some(self.load_theme(parent_name.as_str(), Some(max_depth - 1)))
}
None => Some(self.load_theme("default", Some(max_depth - 1))),
};
if debug && name != theme_config.theme.name {
tracing::warn!(
"Your theme config name is not the name of your loaded theme {} != {}",
name,
theme_config.theme.name
);
}
let theme = Theme::from_foreground_colors(theme_config.theme.name, parent, colors, debug);View on GitHub (pinned to 202f6ad98e)
Solutions
- Flatten the theme inheritance chain to fewer than 10 hops
- Break the cycle: ensure no theme transitively lists itself as a parent (grep parent = in your themes directory and follow the chain)
- Set parent only to themes that exist and terminate (the default theme has no parent)
- Enable theme.debug to see the warn logs tracing which parent name was being loaded when the limit hit
Example fix
# before (themes/a.toml -> themes/b.toml -> themes/a.toml) # a.toml: parent = "b" ; b.toml: parent = "a" => cycle # after (themes/b.toml) [theme] name = "b" # parent = "a" # removed; b now inherits from 'default' [colors] AlertError = "red"
Defensive patterns
Strategy: validation
Validate before calling
// Walk parent links before loading; reject cycles and over-deep chains
fn chain_depth(dir: &std::path::Path, name: &str, seen: &mut Vec<String>) -> Option<usize> {
if seen.iter().any(|s| s == name) { return None; } // cycle
seen.push(name.clone());
let text = std::fs::read_to_string(dir.join(format!("{name}.toml")).ok()?;
let v: toml::Value = text.parse().ok()?;
match v.get("theme").and_then(|t| t.get("parent")).and_then(|p| p.as_str()) {
Some(p) => chain_depth(dir, p, seen).map(|d| d + 1),
None => Some(0),
}
}
// require chain_depth(...) <= 10 before calling load_theme Try / catch
match manager.load_theme_from_file(name, 10) {
Ok(t) => t,
Err(e) if e.to_string().contains("recursion limit") => {
// inheritance chain too deep or cyclic: fall back to 'default'
manager.load_theme("default", None)
}
Err(e) => { /* propagate or fallback */ manager.load_theme("(none)", None) }
} Prevention
- Keep theme inheritance chains short (<= a few levels, hard limit is 10)
- Never let a theme's parent chain revisit a name — check for cycles when authoring layered themes
- Prefer composing colors directly over deep inheritance
- Enable theme.debug to see which parent load hit the limit
When it happens
Trigger: A theme chain of more than 10 files (child.toml -> ... -> 11th ancestor), or a circular parent reference where two themes name each other as parent. Each cycle iteration burns one depth level until max_depth == 0 at theme.rs:475 and the error returns.
Common situations: Users creating layered themes that inherit from one another and accidentally reintroducing an ancestor (a -> b -> c -> a); refactoring a theme family so a parent points back at its own child; excessively deep 'base' theme chains built by hand.
Related errors
- Empty theme directory override and could not find theme else
- Failed to deserialize theme: {}
- failed to create client
- Failed to compute stats
- key file vanished immediately after a concurrent write
AI-assisted analysis of atuinsh/atuin@202f6ad98e (2026-08-16).
Data as JSON: /api/errors/815781a5f4fcac90.
Report an issue: GitHub.