{"record":{"id":"87f62b4765280189","repo":"jdx/mise","slug":"managed-system-path-is-declared-as-both-a-fil","errorCode":null,"errorMessage":"managed system path '{}' is declared as both a file and a directory","messagePattern":"managed system path '(.+?)' is declared as both a file and a directory","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src/system/managed_files.rs","lineNumber":242,"sourceCode":"    let directory_states = directories\n        .iter()\n        .map(|directory| (directory.path.as_path(), directory.state))\n        .collect::<std::collections::HashMap<_, _>>();\n    for (path, (file, base, origin)) in merged_files_from_config(config)? {\n        let state = file.state;\n        let phase = file.phase;\n        match ManagedFileRequest::from_toml(\n            config,\n            path.clone(),\n            file,\n            &base,\n            origin.clone(),\n            secrets,\n        ) {\n            Ok(file) => files.push(file),\n            Err(error) if super::secrets::is_unavailable(&error) => {\n                if directory_states.contains_key(path.as_path()) {\n                    bail!(\n                        \"managed system path '{}' is declared as both a file and a directory\",\n                        path.display()\n                    );\n                }\n                validate_present_ancestors(&path, state, &directory_states)?;\n                unavailable.push(\n                    ResourcePlan::new(\n                        ResourceId::new(\"file\", path.to_string_lossy().into_owned()),\n                        \"not inspected: required secret unavailable\",\n                        \"template rendered\",\n                        ResourceAction::Unknown,\n                    )\n                    .with_origin(origin)\n                    .with_file_phase(phase),\n                );\n            }\n            Err(error) => return Err(error),\n        }","sourceCodeStart":224,"sourceCodeEnd":260,"githubUrl":"https://github.com/jdx/mise/blob/533346cc374382b41ec5ff70536252b2e96e725c/src/system/managed_files.rs#L224-L260","documentation":"Thrown while building managed-file status requests when a path that resolved to an unavailable (secret-backed) file declaration already exists in the set of declared managed directories. A single managed system path cannot simultaneously be a file and a directory; the config is ambiguous, so validation stops. The error names the offending path.","triggerScenarios":"The same path declared once as a managed file (e.g. under bootstrap `files`) and again as a managed directory (under bootstrap `directories`), where the file's secret source was unavailable and the code checked directory states for the collision.","commonSituations":"Merging configs from multiple layers (user/global/project) where one layer declares the path as a file and another as a directory; refactoring a path from file to directory while leaving stale declarations elsewhere.","solutions":["Decide whether the path is a file or a directory and declare it only one way across all config layers.","Search all mise.toml layers for the path and remove the conflicting declaration.","If the path should be a directory containing files, declare the children as files and the parent as a directory — not the same path as both."],"exampleFix":"# before (conflict)\n[bootstrap.files.\"/etc/app/config\"]\ncontent = \"...\"\n[bootstrap.directories]\n\"/etc/app/config\" = true\n\n# after\n[bootstrap.files.\"/etc/app/config\"]\ncontent = \"...\"","handlingStrategy":"validation","validationCode":"file_paths = set(bootstrap.files)\ndir_paths = set(bootstrap.directories)\noverlap = file_paths & dir_paths\nif overlap: raise SystemExit(f'path is both file and directory: {overlap}')","typeGuard":"function isExclusivePath(decls) {\n  return decls.filter(d => d.kind === 'file').every(f =>\n    !decls.some(d => d.kind === 'directory' && d.path === f.path));\n}","tryCatchPattern":null,"preventionTips":["Keep a single source of truth for each managed path's kind.","Grep all config layers for a path before changing it from file to directory.","Automate a pre-apply check that file and directory path sets are disjoint."],"tags":["config","managed-files","conflict","validation"],"backgroundTag":"conflicting-config-options","analyzedSha":"533346cc374382b41ec5ff70536252b2e96e725c","analyzedAt":"2026-09-17T13:35:38.149Z","contentChangedAt":"2026-09-17T13:35:38.149Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}