{"record":{"id":"eb7ad4c3591e7da0","repo":"atuinsh/atuin","slug":"failed-to-deserialize-theme","errorCode":null,"errorMessage":"Failed to deserialize theme: {}","messagePattern":"Failed to deserialize theme: (.+?)","errorType":"validation","errorClass":"std::io::Error","httpStatus":null,"severity":"error","filePath":"crates/atuin-client/src/theme.rs","lineNumber":430,"sourceCode":"\n        config_builder = config_builder\n            .add_source(ConfigFile::new(theme_file.to_str().unwrap(), FileFormat::Toml));\n\n        let config = config_builder.build()?;\n        self.load_theme_from_config(name, config, max_depth)\n    }\n\n    pub fn load_theme_from_config(\n        &mut self,\n        name: &str,\n        config: Config,\n        max_depth: u8,\n    ) -> Result<&Theme, Box<dyn error::Error>> {\n        let debug = self.debug;\n        let theme_config: ThemeConfig = match config.try_deserialize() {\n            Ok(tc) => tc,\n            Err(e) => {\n                return Err(Box::new(Error::new(\n                    ErrorKind::InvalidInput,\n                    format!(\n                        \"Failed to deserialize theme: {}\",\n                        if debug {\n                            e.to_string()\n                        } else {\n                            \"set theme debug on for more info\".to_string()\n                        }\n                    ),\n                )));\n            }\n        };\n        let colors: HashMap<Meaning, String> = theme_config.colors;\n        let parent: Option<&Theme> = match theme_config.theme.parent {\n            Some(parent_name) => {\n                if max_depth == 0 {\n                    return Err(Box::new(Error::new(\n                        ErrorKind::InvalidInput,","sourceCodeStart":412,"sourceCodeEnd":448,"githubUrl":"https://github.com/atuinsh/atuin/blob/900007c48045867e7f44b0f9bc55ad9dbe99ee0d/crates/atuin-client/src/theme.rs#L412-L448","documentation":"The theme file was found and read, but its contents could not be deserialized into a ThemeConfig. The error wraps the underlying deserializer message; when debug mode is off, the detailed reason is replaced with a generic hint, so enable debug to see the real cause.","triggerScenarios":"Calling load_theme_from_config on a config file whose TOML does not match the ThemeConfig schema — unknown keys (if strict), wrong types for colors/parent, or malformed TOML.","commonSituations":"Hand-edited theme files with typos, theme files from older/newer Atuin versions with changed schema, copying a theme written for a different tool, or invalid TOML syntax.","solutions":["Enable debug mode to surface the underlying deserializer error message, then fix the offending key/type in the theme file.","Validate the theme file's TOML syntax and that every field matches ThemeConfig's expected types (colors: map of meaning -> string; parent: optional string).","Compare against a known-good stock theme file and remove unsupported keys.","Check the theme file version matches your Atuin version."],"exampleFix":"// before: colors = { bg = \"#fff\" }  // unknown key fails schema\n// after:  colors = { background = \"#ffffff\" }","handlingStrategy":"try-catch","validationCode":"// pre-validate the theme file parses as TOML and has expected key types\nlet raw = std::fs::read_to_string(&path)?;\nlet toml: toml::Value = raw.parse()?;\nif let Some(colors) = toml.get(\"colors\").and_then(|c| c.as_table()) {\n    for (k, v) in colors {\n        assert!(v.is_str(), \"colors.{k} must be a string, got {v}\");\n    }\n}","typeGuard":"fn is_parsable_theme(raw: &str) -> bool {\n    raw.parse::<toml::Value>()\n        .ok()\n        .and_then(|v| v.get(\"colors\").and_then(|c| c.as_table()).map(|t| {\n            t.values().all(|val| val.as_str().is_some())\n        }))\n        .unwrap_or(false)\n}","tryCatchPattern":"match theme_engine.load_theme_from_file(name, 3) {\n    Ok(t) => apply(t),\n    Err(e) if e.to_string().contains(\"Failed to deserialize theme\") => {\n        eprintln!(\"theme '{name}' invalid; check keys/types (run with debug for details)\");\n        apply(default_theme());\n    }\n    Err(e) => return Err(e),\n}","preventionTips":["Enable debug logging once to see the exact deserializer message","Edit theme files starting from a stock theme rather than from scratch","After Atuin upgrades, re-check custom themes against schema changes","Run the TOML file through a linter/validator before using it"],"tags":["theme","config","deserialization"],"backgroundTag":"config-type-mismatch","analyzedSha":"900007c48045867e7f44b0f9bc55ad9dbe99ee0d","analyzedAt":"2026-09-19T12:52:51.491Z","contentChangedAt":"2026-09-19T12:52:51.491Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}