atuinsh/atuin · warning · std::io::Error
Failed to deserialize theme: {}
Error message
Failed to deserialize theme: {} What it means
Thrown by ThemeManager::load_theme_from_config when the config crate's try_deserialize() of the theme TOML into ThemeConfig fails. It is wrapped in io::ErrorKind::InvalidInput, and the underlying cause string is redacted to 'set theme debug on for more info' unless debug was enabled in ThemeManager::new (wired to the theme.debug setting in config, settings.rs:1532). Like error 0, ThemeManager::load_theme catches it and degrades to the '(none)' theme, so users see a warning log with the theme silently not applied.
Source
Thrown at crates/atuin-client/src/theme.rs:459
theme_file.to_str().unwrap(),
FileFormat::Toml,
));
let config = config_builder.build()?;
self.load_theme_from_config(name, config, max_depth)
}
pub fn load_theme_from_config(
&mut self,
name: &str,
config: Config,
max_depth: u8,
) -> Result<&Theme, Box<dyn error::Error>> {
let debug = self.debug;
let theme_config: ThemeConfig = match config.try_deserialize() {
Ok(tc) => tc,
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,View on GitHub (pinned to 202f6ad98e)
Solutions
- Set theme.debug = true in config.toml to get the full deserialization error message in the warning
- Fix the reported key/type in the theme TOML so it matches the ThemeConfig schema (colors as strings keyed by meaning, theme.name/theme.parent as strings)
- Copy a working theme (e.g. the default theme file from the Atuin repo) and modify it incrementally
- Rename or remove the broken {name}.toml so the fallback to built-in themes is explicit
Example fix
# before (themes/mytheme.toml) [theme] name = "mytheme" [colors] error = "red" # unknown key 'error' # after [theme] name = "mytheme" [colors] AlertError = "red" # valid Meaning key, string value
Defensive patterns
Strategy: validation
Validate before calling
// Validate theme TOML against the schema before Atuin loads it
let raw = std::fs::read_to_string(theme_path)?;
let value: toml::Value = raw.parse()?; // syntax check
let colors = value.get("colors").and_then(|c| c.as_table());
if colors.is_none() { /* schema mismatch: fix before shipping the theme */ } Type guard
fn is_valid_theme_config(v: &toml::Value) -> bool {
v.get("theme")
.and_then(|t| t.get("name"))
.and_then(|n| n.as_str())
.is_some()
&& v.get("colors")
.and_then(|c| c.as_table())
.is_some_and(|t| t.values().all(|v| v.as_str().is_some()))
} Try / catch
match manager.load_theme_from_file(name, 10) {
Ok(t) => t,
Err(e) if e.to_string().contains("Failed to deserialize theme") => {
// enable theme.debug for details, fall back to a builtin theme meanwhile
manager.load_theme("default", None)
}
Err(e) => { /* propagate */ manager.load_theme("(none)", None) }
} Prevention
- Keep theme.debug = true in config while iterating on custom themes to see real deserialization errors
- Start custom themes from a copy of a known-good theme file
- Use string color values and valid meaning keys exactly as documented in ThemeConfig
- Lint theme TOML in CI when themes live in a dotfiles repo
When it happens
Trigger: A {name}.toml in the themes directory whose [theme] or colors table does not match ThemeConfig: unknown color keys (not valid Meaning variants), non-string color values, a missing or wrongly-typed theme.name or theme.parent, or a file that built as a Config but fails typed deserialization. Also reachable via load_theme_from_config directly with a programmatically built Config.
Common situations: Hand-editing a theme TOML and typos like `colour` instead of color keys, `red = "Meaning::AlertError"` inverted key/value order, using a theme written for a newer/older Atuin with a changed schema, or trailing types like integers where color strings are expected. Users migrating custom themes between Atuin versions frequently hit this.
Related errors
- Empty theme directory override and could not find theme else
- Parent requested but we hit the recursion limit
- 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/eb7ad4c3591e7da0.
Report an issue: GitHub.