astrid-runtime/astrid · error

WinFsp service mountpoint is not empty

Error message

WinFsp service mountpoint is not empty

What it means

Before mounting, the target mountpoint directory must be completely empty — WinFsp will present the virtual filesystem's contents there, and pre-existing files would be shadowed or mixed with the mount. If std::fs::read_dir finds any entry in the directory, validate_service_launch bails rather than silently hiding or clobbering existing data.

Source

Thrown at crates/astrid-storage-provider-winfsp/src/win.rs:311

            .components()
            .any(|component| matches!(component, std::path::Component::ParentDir))
    {
        bail!("WinFsp service mountpoint is malformed");
    }
    if is_public_mountpoint(&launch.mountpoint)
        || launch.mountpoint.parent().is_none()
        || launch.mountpoint == lease.resource_path
        || launch.mountpoint.starts_with(&lease.resource_path)
        || lease.resource_path.starts_with(&launch.mountpoint)
    {
        bail!("WinFsp service mountpoint is public or overlaps the lease resource");
    }
    platform_fs::validate_private_directory(&launch.mountpoint)
        .context("validate private WinFsp mountpoint")?;
    platform_fs::verify_no_redirects(&launch.mountpoint)
        .context("reject redirected WinFsp mountpoint")?;
    if std::fs::read_dir(&launch.mountpoint)?.next().is_some() {
        bail!("WinFsp service mountpoint is not empty");
    }
    if !launch.control_path.is_absolute()
        || launch
            .control_path
            .components()
            .any(|component| matches!(component, std::path::Component::ParentDir))
        || launch.control_path != lease.resource_path.join("process-control.sock")
    {
        bail!("WinFsp service control path is malformed");
    }
    let control_parent = launch
        .control_path
        .parent()
        .context("WinFsp service control path has no parent")?;
    platform_fs::validate_private_directory(control_parent)
        .context("validate private WinFsp control parent")?;
    platform_fs::verify_no_redirects(&launch.control_path)
        .context("reject redirected WinFsp control path")?;

View on GitHub (pinned to affd8760f4)

Solutions

  1. Empty the mountpoint directory before launching (move its contents aside or delete them after user confirmation).
  2. Use a fresh, dedicated per-mount directory (e.g. named by mount_id) instead of a shared folder, so it is empty by construction.
  3. Check the mountpoint for leftover content in your launcher and fail early with a user-facing message rather than reaching the service.
  4. If the previous mount crashed, clean up its mountpoint during recovery before issuing a new launch descriptor.

Example fix

// before
spawn_service(launch); // mountpoint may contain leftovers
// after
for entry in fs::read_dir(&mountpoint)? { /* stash or delete entries */ }
spawn_service(launch);
Defensive patterns

Strategy: validation

Validate before calling

if std::fs::read_dir(&mountpoint)?.next().is_some() {
    return Err(anyhow!("mountpoint {} must be empty before mounting", mountpoint.display()));
}

Try / catch

match start_mount(&launch) {
    Err(e) if e.to_string().contains("mountpoint is not empty") => {
        archive_mountpoint_contents(&launch.mountpoint)?;
        start_mount(&launch)
    }
    other => other,
}

Prevention

When it happens

Trigger: service_main -> validate_service_launch where std::fs::read_dir(&launch.mountpoint)?.next().is_some(): any file, subdirectory, or even a leftover control endpoint exists inside the mountpoint directory at launch time.

Common situations: Remounting after an unclean shutdown that left stale files in the mountpoint; a previous mount's contents were materialized to disk; users pre-created files in the folder they designated as the mountpoint; a prior failed launch left a partially-copied state.

Related errors


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