{"record":{"id":"815781a5f4fcac90","repo":"atuinsh/atuin","slug":"parent-requested-but-we-hit-the-recursion-limit","errorCode":null,"errorMessage":"Parent requested but we hit the recursion limit","messagePattern":"Parent requested but we hit the recursion limit","errorType":"exception","errorClass":"std::io::Error","httpStatus":null,"severity":"error","filePath":"crates/atuin-client/src/theme.rs","lineNumber":447,"sourceCode":"            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,\n                        \"Parent requested but we hit the recursion limit\",\n                    )));\n                }\n                Some(self.load_theme(parent_name.as_str(), Some(max_depth - 1)))\n            }\n            None => Some(self.load_theme(\"default\", Some(max_depth - 1))),\n        };\n\n        if debug && name != theme_config.theme.name {\n            tracing::warn!(\n                \"Your theme config name is not the name of your loaded theme {} != {}\",\n                name,\n                theme_config.theme.name\n            );\n        }\n\n        let theme = Theme::from_foreground_colors(theme_config.theme.name, parent, &colors, debug);","sourceCodeStart":429,"sourceCodeEnd":465,"githubUrl":"https://github.com/atuinsh/atuin/blob/900007c48045867e7f44b0f9bc55ad9dbe99ee0d/crates/atuin-client/src/theme.rs#L429-L465","documentation":"Themes can inherit from a parent theme, and Atuin resolves parents recursively. If the parent chain is deeper than max_depth allows (or the chain contains a cycle), resolution stops and this InvalidInput error is returned rather than recursing forever.","triggerScenarios":"load_theme_from_config encounters a theme whose `parent` field is set while max_depth is 0 — caused by a parent chain longer than the allowed depth or a circular parent reference (theme A -> theme B -> theme A).","commonSituations":"Accidentally circular theme inheritance, very long inheritance chains exceeding the recursion limit passed by the caller, or themes copied from setups that chain multiple custom parents.","solutions":["Find and break the cycle: open each theme in the parent chain and remove or fix the `parent` reference that points back to an ancestor.","Flatten the inheritance: copy the parent's colors into the child theme and drop the `parent` field.","If the chain is legitimately deep, load with a higher max_depth value."],"exampleFix":"# before (cycle)\n# mytheme.toml\nparent = \"base\"   # base.toml also has parent = \"mytheme\"\n\n# after\nparent = \"\"  # or remove the parent line","handlingStrategy":"validation","validationCode":"// detect cycles in the parent chain before loading\nfn has_parent_cycle(name: &str, seen: &mut Vec<String>) -> bool {\n    if seen.contains(&name.to_string()) { return true; }\n    seen.push(name.to_string());\n    match parent_of(name) {\n        Some(p) => has_parent_cycle(&p, seen),\n        None => false,\n    }\n}","typeGuard":"fn parent_chain_depth_ok(name: &str, limit: u8) -> bool {\n    let mut cur = Some(name.to_string());\n    let mut depth: u8 = 0;\n    while let Some(n) = cur {\n        depth += 1;\n        if depth > limit { return false; }\n        cur = parent_of(&n);\n    }\n    true\n}","tryCatchPattern":"match theme_engine.load_theme(name, 3) {\n    Ok(t) => apply(t),\n    Err(e) if e.to_string().contains(\"recursion limit\") => {\n        eprintln!(\"theme '{name}' parent chain too deep or cyclic; flattening\");\n        apply(flatten_theme(name));\n    }\n    Err(e) => return Err(e),\n}","preventionTips":["Never set a theme's parent to itself or to a descendant","Keep parent chains shallow (<= 2 levels); flatten when possible","When copying themes between setups, re-check every parent reference exists and acyclic"],"tags":["theme","recursion","config"],"backgroundTag":"invalid-config-value","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"}