{"record":{"id":"18c92d154f241c9e","repo":"jdx/mise","slug":"managed-system-path-must-be-absolute","errorCode":null,"errorMessage":"managed system path must be absolute: {}","messagePattern":"managed system path must be absolute: (.+?)","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src/system/managed_files.rs","lineNumber":1194,"sourceCode":"            Self::File\n        } else if metadata.file_type().is_dir() {\n            Self::Directory\n        } else if metadata.file_type().is_symlink() {\n            Self::Symlink\n        } else {\n            Self::Other\n        }\n    }\n}\n\nfn absolute_target(path: &str) -> Result<PathBuf> {\n    let path = crate::file::replace_path(Path::new(path));\n    validate_privileged_target(&path)\n}\n\nfn validate_privileged_target(path: &Path) -> Result<PathBuf> {\n    if !path.is_absolute() {\n        bail!(\"managed system path must be absolute: {}\", path.display());\n    }\n    let path = path.absolutize()?.to_path_buf();\n    if path == Path::new(\"/\") {\n        bail!(\"refusing to manage the filesystem root\");\n    }\n    Ok(path)\n}\n\nfn parse_mode(mode: Option<&str>, default: u32) -> Result<u32> {\n    let Some(mode) = mode else {\n        return Ok(default);\n    };\n    let mode = mode.strip_prefix(\"0o\").unwrap_or(mode);\n    let parsed = u32::from_str_radix(mode, 8).wrap_err(\"mode must be an octal string\")?;\n    if parsed > 0o7777 {\n        bail!(\"mode must be between 0000 and 7777\");\n    }\n    Ok(parsed)","sourceCodeStart":1176,"sourceCodeEnd":1212,"githubUrl":"https://github.com/jdx/mise/blob/9dcfcaa0dc8747a2577d3270b69bb9d8313b2807/src/system/managed_files.rs#L1176-L1212","documentation":"Managed file and directory targets go through absolute_target() -> validate_privileged_target(), which requires an absolute path. Relative paths are rejected because the privileged helper runs with a different working directory, so a relative target would resolve to a different location under root than under the invoking user.","triggerScenarios":"A [bootstrap.files] or [bootstrap.directories] key like \"conf/app.conf\" (no leading slash) in mise.toml - anything where Path::is_absolute() is false.","commonSituations":"Copying a relative path from a deploy script or template into mise.toml; assuming mise prepends the project directory (it does not - targets are system paths like /etc/...).","solutions":["Change the config key to an absolute path, e.g. \"/etc/app/app.conf\"","If you meant a project-local file, manage it with a normal mise task or template instead of managed system files"],"exampleFix":"# before\n[bootstrap.files]\n\"conf/app.conf\" = { content = \"...\" }\n\n# after\n[bootstrap.files]\n\"/etc/app/app.conf\" = { content = \"...\", mode = \"0644\" }","handlingStrategy":"validation","validationCode":"let path = std::path::Path::new(key);\nif !path.is_absolute() {\n    return Err(eyre::eyre!(\"managed system path must be absolute: {key}\"));\n}","typeGuard":"fn is_valid_managed_path(p: &str) -> bool {\n    std::path::Path::new(p).is_absolute() && p != \"/\"\n}","tryCatchPattern":null,"preventionTips":["Always author managed paths as full absolute system paths","Lint mise.toml in CI for relative keys under [bootstrap.files]/[bootstrap.directories]"],"tags":["validation","path","config","bootstrap","managed-files"],"backgroundTag":"relative-path-rejected","analyzedSha":"9dcfcaa0dc8747a2577d3270b69bb9d8313b2807","analyzedAt":"2026-08-17T14:28:50.624Z","schemaVersion":2},"datasetVersion":"2026-08-21T23:17:16.201Z"}