astrid-runtime/astrid · error

mountpoint must be owned by the current OS user: {}

Error message

mountpoint must be owned by the current OS user: {}

What it means

prepare_mountpoint validates the user-supplied FUSE mountpoint directory before mounting. It refuses to proceed if the existing directory is not owned by the current OS user (uid mismatch between symlink_metadata and getuid). This prevents a FUSE mount over a directory controlled by another user, which could leak or capture I/O across privilege boundaries.

Source

Thrown at crates/astrid-storage-provider-fuse/src/mountpoint.rs:43

            .join(leaf)
    });
    if !requested.is_absolute() {
        bail!("mountpoint must be absolute");
    }
    let existed = requested.symlink_metadata().is_ok();
    if !existed {
        std::fs::create_dir_all(&requested)
            .with_context(|| format!("create mountpoint {}", requested.display()))?;
    }
    astrid_core::platform_fs::verify_no_redirects(&requested)
        .with_context(|| format!("reject redirected mountpoint {}", requested.display()))?;
    let metadata = std::fs::symlink_metadata(&requested)?;
    if !metadata.is_dir() {
        bail!("mountpoint is not a directory: {}", requested.display());
    }
    let expected_uid = u32::from(getuid());
    if metadata.uid() != expected_uid {
        bail!(
            "mountpoint must be owned by the current OS user: {}",
            requested.display()
        );
    }
    let mode = metadata.permissions().mode();
    if !existed {
        std::fs::set_permissions(&requested, Permissions::from_mode(0o700))?;
    } else if mode & 0o077 != 0 {
        bail!("mountpoint must be owner-private: {}", requested.display());
    }
    if std::fs::read_dir(&requested)?.next().is_some() {
        bail!("mountpoint is not empty: {}", requested.display());
    }
    let canonical = requested
        .canonicalize()
        .with_context(|| format!("canonicalize mountpoint {}", requested.display()))?;
    if mountinfo_contains(&canonical)? {
        bail!("mountpoint is already mounted: {}", canonical.display());

View on GitHub (pinned to affd8760f4)

Solutions

  1. chown the mountpoint directory to the user running the FUSE service (chown $(id -u) <path>)
  2. Remove the directory so prepare_mountpoint recreates it with correct ownership
  3. Run the service as the user who owns the directory
  4. Verify with stat -c '%u' <path> that the uid matches the running process

Example fix

// before
sudo mkdir /mnt/myfuse   # owned by root
// after
sudo mkdir /mnt/myfuse && sudo chown $(id -u):$(id -g) /mnt/myfuse
Defensive patterns

Strategy: validation

Validate before calling

use nix::unistd::getuid;
fn mountpoint_owned_by_current_user(path: &std::path::Path) -> std::io::Result<bool> {
    let md = std::fs::symlink_metadata(path)?;
    Ok(md.is_dir() && md.uid() == u32::from(getuid()))
}

Type guard

fn is_owned_by_current_user(md: &std::fs::Metadata) -> bool {
    md.is_dir() && md.uid() == u32::from(nix::unistd::getuid())
}

Try / catch

match prepare_mountpoint(&path) {
    Err(e) if e.to_string().contains("owned by the current OS user") => {
        eprintln!("fix ownership: chown {} $(id -u)", path.display());
    }
    Err(e) => return Err(e),
    Ok(mount) => mount,
}

Prevention

When it happens

Trigger: Calling prepare_mountpoint with a path to a pre-existing directory owned by another uid (e.g. root-created directory, another user's home dir, or a directory whose ownership changed after creation).

Common situations: Running the service under systemd or a container as a different user than the one that created the mountpoint directory; an admin pre-creating /mnt/myfuse as root; chown'ing the mountpoint by mistake.

Understand the failure class

Background: Permission denied / not authorized / 403 Forbidden: access-control rejections when the caller lacks the required role, grant, or ownership — this error's family across 18 libraries.

Related errors


AI-assisted analysis of astrid-runtime/astrid@affd8760f4 (2026-09-09). Data as JSON: /api/errors/161f1d23e9689efd. Report an issue: GitHub.