{"record":{"id":"9db22ad810fc4432","repo":"jdx/mise","slug":"bootstrap-directories-recursive-is-only-va","errorCode":null,"errorMessage":"[bootstrap.directories].\"{}\": recursive is only valid with state = \"absent\"","messagePattern":"\\[bootstrap\\.directories\\]\\.\"(.+?)\": recursive is only valid with state = \"absent\"","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src/system/managed_files.rs","lineNumber":642,"sourceCode":"        crate::file::replace_path(source)\n    } else {\n        PathBuf::from(source)\n    };\n    if source.is_absolute() {\n        source\n    } else {\n        base.join(source)\n    }\n}\n\nimpl ManagedDirectoryRequest {\n    fn from_toml(\n        path: PathBuf,\n        config: ManagedDirectoryTomlConfig,\n        origin: ResourceOrigin,\n    ) -> Result<Self> {\n        if config.state == ManagedState::Present && config.recursive {\n            bail!(\n                \"[bootstrap.directories].\\\"{}\\\": recursive is only valid with state = \\\"absent\\\"\",\n                path.display()\n            );\n        }\n        Ok(Self {\n            path,\n            owner: nonempty(\"owner\", config.owner)?,\n            group: nonempty(\"group\", config.group)?,\n            mode: parse_mode(config.mode.as_deref(), 0o755)?,\n            state: config.state,\n            recursive: config.recursive,\n            replace: config.replace,\n            notify: config.notify,\n            origin,\n            inspection: None,\n        })\n    }\n","sourceCodeStart":624,"sourceCodeEnd":660,"githubUrl":"https://github.com/jdx/mise/blob/afd2eddd3a50c16190efc1c7e94404b48f72af57/src/system/managed_files.rs#L624-L660","documentation":"Raised by ManagedDirectoryRequest::from_toml for [bootstrap.directories] entries. `recursive = true` (recursive removal of the tree) is only meaningful when state = \"absent\"; combining it with state = \"present\" is contradictory — creation has no meaningful notion of recursion via this flag — so the entry is rejected at parse time.","triggerScenarios":"Parsing a [bootstrap.directories.\"<path>\"] TOML entry where `recursive = true` AND state = \"present\" (or present is the default state).","commonSituations":"Copying an absent-removal entry and flipping state to \"present\" without removing `recursive`; assuming `recursive = true` creates parent directories and setting it on a create entry; bulk-generating entries where the flag leaks across entries.","solutions":["Remove `recursive = true` from the present-state directory entry (creating a directory already creates parents).","If you intended recursive removal of the tree, set state = \"absent\" and keep recursive = true.","Re-run bootstrap to confirm the config parses."],"exampleFix":"# before\n[[bootstrap.directories]]\npath = \"/var/lib/myapp/cache\"\nstate = \"present\"\nrecursive = true\n\n# after\n[[bootstrap.directories]]\npath = \"/var/lib/myapp/cache\"\nstate = \"present\"","handlingStrategy":"validation","validationCode":"fn validate_directory_entry(entry: &ManagedDirectoryTomlConfig) -> Result<(), String> {\n    if entry.state == ManagedState::Present && entry.recursive {\n        return Err(\"recursive is only valid with state = \\\"absent\\\"\".into());\n    }\n    Ok(())\n}","typeGuard":"fn invalid_recursive(entry: &ManagedDirectoryTomlConfig) -> bool {\n    entry.state == ManagedState::Present && entry.recursive\n}","tryCatchPattern":null,"preventionTips":["Use `recursive = true` only on state = \"absent\" directory entries for tree removal.","Directory creation already creates parents; do not add recursive for that purpose.","Flip state flags and body flags together when converting entries between present/absent."],"tags":["config","toml","bootstrap","validation"],"backgroundTag":"conflicting-config-options","analyzedSha":"afd2eddd3a50c16190efc1c7e94404b48f72af57","analyzedAt":"2026-09-09T01:38:25.179Z","contentChangedAt":"2026-09-09T01:38:25.179Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}