rustfs/rustfs · error · std::io::Error

cannot safely reopen the publication root for pathname acces

Error message

cannot safely reopen the publication root for pathname access

What it means

Reopening the publication root for pathname access needs the last segment of destination_parent to open it relative to its own parent. If destination_parent is a filesystem root (C:\ or a UNC share root), file_name() returns None, the reopen is impossible, and the guard fails closed with PermissionDenied rather than falling back to unguarded pathname access.

Source

Thrown at crates/ecstore/src/disk/os.rs:2843

            use windows_sys::Win32::Storage::FileSystem::{FILE_SHARE_READ, FILE_SHARE_WRITE};

            let relative = directory.strip_prefix(&self.destination_parent).map_err(|_| {
                io::Error::new(
                    io::ErrorKind::InvalidInput,
                    "guarded path must remain below the rename destination parent",
                )
            })?;
            for component in relative.components() {
                if !matches!(component, Component::Normal(_) | Component::CurDir) {
                    return Err(io::Error::new(
                        io::ErrorKind::InvalidInput,
                        "guarded destination path contains an invalid component",
                    ));
                }
            }

            let component = self.destination_parent.file_name().ok_or_else(|| {
                io::Error::new(
                    io::ErrorKind::PermissionDenied,
                    "cannot safely reopen the publication root for pathname access",
                )
            })?;
            let parent_index = self.destination_parent_guard.handles.len().checked_sub(2).ok_or_else(|| {
                io::Error::new(
                    io::ErrorKind::PermissionDenied,
                    "cannot safely reopen the publication root for pathname access",
                )
            })?;
            let mut handles = self.destination_parent_guard.handles[..=parent_index].to_vec();
            let parent = handles
                .last()
                .ok_or_else(|| io::Error::other("Windows destination guard lost its parent handle"))?;
            let mut relative_components = relative
                .components()
                .filter_map(|component| match component {
                    Component::Normal(component) => Some(component),

View on GitHub (pinned to 201c653dcd)

Solutions

  1. Configure the storage path as a named subdirectory of the volume, e.g. E:\rustfs-data instead of E:\
  2. Validate at startup that the configured data path has a file name and fail configuration early with a clear message

Example fix

# before
path: "E:\"

# after
path: "E:\rustfs-data"
Defensive patterns

Strategy: validation

Validate before calling

let data_dir = load_config().data_dir;
if data_dir.file_name().is_none() {
    return Err(config_error("storage path must be a named directory, not a volume root"));
}

Type guard

fn has_file_name(p: &Path) -> bool { p.file_name().is_some() }

Try / catch

Err(e) if e.kind() == io::ErrorKind::PermissionDenied && e.to_string().contains("publication root for pathname access") => reconfigure the data path to a named subdirectory; restart required

Prevention

When it happens

Trigger: The storage/data directory is configured at the root of a volume, e.g. E:\ or \\server\share, leaving no named segment for the handle-relative reopen.

Common situations: Quick test setups pointing at a bare drive; misformatted config such as path: "C:\"; automation mounting a volume and using its root directly as the pool path.

Related errors


AI-assisted analysis of rustfs/rustfs@201c653dcd (2026-08-20). Data as JSON: /api/errors/a6c6c36127a077d0. Report an issue: GitHub.