jdx/mise · error

invalid managed directory path: {}

Error message

invalid managed directory path: {}

What it means

Thrown when a managed directory path is not absolute or contains non-normal path components (like `..`, `.`, or a root/curdir component) that cannot be safely mapped into the component-by-component openat walk. The function requires a clean absolute path so each component can be opened with O_NOFOLLOW semantics. This is a strict input validation protecting the safe directory-tree builder.

Source

Thrown at src/system/managed_files.rs:1594

    followed_symlinks: usize,
) -> Result<std::os::fd::OwnedFd> {
    use nix::fcntl::{AtFlags, OFlag, open, openat};
    use nix::sys::stat::{Mode, SFlag, fstat, fstatat, mkdirat};

    if followed_symlinks > 40 {
        bail!(
            "too many symbolic links in managed directory {}",
            path.display()
        );
    }

    let components = path
        .strip_prefix(Path::new("/"))
        .wrap_err_with(|| format!("managed directory must be absolute: {}", path.display()))?
        .components()
        .map(|component| match component {
            std::path::Component::Normal(name) => Ok(name.to_os_string()),
            _ => bail!("invalid managed directory path: {}", path.display()),
        })
        .collect::<Result<Vec<_>>>()?;

    let flags = OFlag::O_RDONLY | OFlag::O_DIRECTORY | OFlag::O_NOFOLLOW;
    let mut directory = open(Path::new("/"), flags, Mode::empty())?;
    let mut current = PathBuf::from("/");
    for (index, name) in components.iter().enumerate() {
        let component_path = current.join(name);
        directory = match openat(&directory, name.as_os_str(), flags, Mode::empty()) {
            Ok(directory) => directory,
            Err(open_error) => {
                let metadata = fstatat(&directory, name.as_os_str(), AtFlags::AT_SYMLINK_NOFOLLOW);
                if metadata.is_ok_and(|metadata| {
                    SFlag::from_bits_truncate(metadata.st_mode).contains(SFlag::S_IFLNK)
                }) {
                    let parent = fstat(&directory)?;
                    if parent.st_uid != 0 || parent.st_mode & 0o022 != 0 {
                        bail!(

View on GitHub (pinned to afd2eddd3a)

Solutions

  1. Convert the path to an absolute, normalized form before calling (absolutize/canonicalize, then clean `.`/`..` components)
  2. Fix the configured path so it is absolute and contains only normal components
  3. Reject or normalize user-supplied paths at your config-loading boundary
  4. Re-run with the corrected absolute path

Example fix

// before
open_or_create_directory_tree("opt/tools/../share")?;
// after
let path = path.absolutize()?.to_path_buf(); // yields /cwd/opt/share
open_or_create_directory_tree(&path)?;
Defensive patterns

Strategy: validation

Validate before calling

fn is_clean_absolute(path: &Path) -> bool {
    path.is_absolute()
        && path.strip_prefix("/").ok()
            .map(|rest| rest.components().all(|c| matches!(c, std::path::Component::Normal(_))))
            .unwrap_or(false)
}

Type guard

fn normalize(path: &Path) -> Option<std::path::PathBuf> {
    let abs = path.absolutize().ok()?.to_path_buf();
    if is_clean_absolute(&abs) { Some(abs) } else { None }
}

Try / catch

match result {
    Err(e) if e.to_string().contains("invalid managed directory path") => {
        let cleaned = absolutize_and_normalize(path)?;
        retry_with(&cleaned);
    }
    Err(e) => return Err(e),
    Ok(v) => v,
}

Prevention

When it happens

Trigger: Passing a relative path, or a path containing `..` / `.` components (e.g. `/opt/tools/../share` or `tools/share`) to the managed directory open/create API; strip_prefix("/") fails for relative paths.

Common situations: Config values built by string concatenation without normalization; user-supplied paths with `..`; paths produced by joining with environment variables that contain relative fragments; forgetting to call absolutize/canonicalize before the call.

Understand the failure class

Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.

Related errors


AI-assisted analysis of jdx/mise@afd2eddd3a (2026-09-09). Data as JSON: /api/errors/e773fbecb43394a8. Report an issue: GitHub.