astrid-runtime/astrid · error

mountpoint is not empty: {}

Error message

mountpoint is not empty: {}

What it means

prepare_mountpoint refuses to mount over a non-empty directory. After enforcing permissions it reads the directory and bails if any entry exists, since mounting over populated directories hides their contents and can hide stale data.

Source

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

    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());
    }
    Ok((canonical, !existed))
}

/// Return current owner identity for synthetic inode metadata.
pub(crate) fn owner_ids() -> (u32, u32) {
    (getuid().into(), getgid().into())
}

/// Remove a dead FUSE mount if one remains at an exact canonical path.
pub(crate) fn lazy_unmount(mountpoint: &Path) -> Result<()> {
    use nix::mount::MntFlags;

View on GitHub (pinned to affd8760f4)

Solutions

  1. Empty the directory (rm -rf <mountpoint>/* including dotfiles) before mounting
  2. Remove and recreate the directory so the provider creates a fresh private one
  3. Recover files from a previous failed mount before retrying
  4. Check for leftover session artifacts (e.g. from rollback cleanup failures)

Example fix

// before
ls /mnt/myfuse  # stale session files remain
// after
rm -rf /mnt/myfuse && mkdir -m 700 /mnt/myfuse
Defensive patterns

Strategy: validation

Validate before calling

fn mountpoint_is_empty(path: &std::path::Path) -> std::io::Result<bool> {
    Ok(std::fs::read_dir(path)?.next().is_none())
}

Try / catch

match prepare_mountpoint(&path) {
    Err(e) if e.to_string().contains("not empty") => {
        eprintln!("empty {} (check for stale session artifacts) first", path.display());
    }
    other => other?,
}

Prevention

When it happens

Trigger: Calling the mount flow with an existing directory that contains files or subdirectories (leftovers from a previous run, user files, or a lost+found).

Common situations: Re-running after a crashed session left artifacts in the mountpoint; pointing the mount at a directory already holding user data; stale files left by a failed rollback.

Understand the failure class

Background: "already exists" / EEXIST / FileAlreadyExistsException: what the 'file already exists' error means and how to fix it — this error's family across 37 libraries.

Related errors


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