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
- Empty the mountpoint directory before launching (move its contents aside or delete them after user confirmation).
- Use a fresh, dedicated per-mount directory (e.g. named by mount_id) instead of a shared folder, so it is empty by construction.
- Check the mountpoint for leftover content in your launcher and fail early with a user-facing message rather than reaching the service.
- 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
- Provision a fresh empty directory per mount instead of reusing folders
- Clean the mountpoint after unclean shutdowns before remounting
- Ask users to designate an empty folder; check it in your launcher before spawning the service
- During recovery, move leftover mountpoint contents to a backup path rather than deleting blindly
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
- mountpoint is not a directory: {}
- WinFsp service mountpoint is malformed
- WinFsp service mountpoint is public or overlaps the lease re
- capsule source is neither a directory nor a regular file: {}
- legacy env/secret path is not a regular directory: {}
AI-assisted analysis of astrid-runtime/astrid@affd8760f4 (2026-09-09).
Data as JSON: /api/errors/821ebf7908179d06.
Report an issue: GitHub.