astrid-runtime/astrid · error
mountpoint is already mounted: {}
Error message
mountpoint is already mounted: {} What it means
ensure_mountpoint_available finds a registry record for the mountpoint, confirms the kernel lease is live and metadata matches, then probes the running FUSE service via a Status control request. If the service answers with matching access, the mountpoint is genuinely mounted and serving — remounting would fail — so the provider bails telling the user the mountpoint is already mounted.
Source
Thrown at crates/astrid-storage-provider-fuse/src/main.rs:820
.to_owned();
let registry: BTreeMap<String, registry::MountRecord> = registry::load_registry()?;
let Some(record) = registry.get(&key).cloned() else {
return Ok(());
};
let status = kernel_lease_status(client, &record.mount_id).await?;
let Some(status) = status else {
cleanup_stale_record(client, acting_principal, &record).await?;
return Ok(());
};
validate_record(&record, &status)?;
match call_control(
&record.control_path,
&ControlRequest::Status {
requested_by: record.requested_by.clone(),
},
) {
Ok(ControlResponse::Status { access }) if access == status.access => {
bail!("mountpoint is already mounted: {}", mountpoint.display())
},
Ok(ControlResponse::Status { access }) => {
bail!("registered FUSE service access {access:?} does not match its lease")
},
Ok(_) => bail!("registered FUSE service returned an incompatible status response"),
Err(_) => {
cleanup_stale_record(client, acting_principal, &record).await?;
Ok(())
},
}
}
async fn cleanup_stale_record(
client: &mut AdminClient,
acting_principal: &astrid_core::PrincipalId,
record: ®istry::MountRecord,
) -> Result<()> {
let lease_is_live = kernel_lease_status(client, &record.mount_id)View on GitHub (pinned to affd8760f4)
Solutions
- Treat it as success if the mount already matches your intent: check status first and skip mounting if active
- Unmount the existing mount first (provider unmount command or fusermount -u) then remount if a fresh mount is required
- Serialize mount operations (locks/script guards) so concurrent runs don't race on the same mountpoint
- If the existing mount is unwanted/stale, unmount it with the requesting principal so the registry record is cleaned
Example fix
// before: blind remount
mount(client, &principal, mountpoint).await?;
// after: idempotent check
if control_status_says_mounted(mountpoint) {
eprintln!("{} already mounted, skipping", mountpoint.display());
} else {
mount(client, &principal, mountpoint).await?;
} Defensive patterns
Strategy: validation
Validate before calling
// Probe before mounting: is the mountpoint already served?
if let Ok(Some(record)) = registry::record_for_mountpoint(mountpoint) {
if let Ok(ControlResponse::Status { .. }) = call_control(&record.control_path, &ControlRequest::Status { requested_by: record.requested_by.clone() }) {
eprintln!("{} already mounted; skipping", mountpoint.display());
return Ok(());
}
} Type guard
fn mountpoint_in_use(mountpoint: &Path) -> bool {
// /proc/mounts or findmnt check for an active FUSE mount at this path
std::fs::read_to_string("/proc/mounts")
.map(|m| m.lines().any(|l| l.split_whitespace().nth(1) == Some(&mountpoint.to_string_lossy())))
.unwrap_or(false)
} Try / catch
match mount(client, &principal, mountpoint).await {
Err(e) if e.to_string().contains("mountpoint is already mounted") => {
// idempotent success: the mount already exists with the same access
Ok(())
}
other => other,
} Prevention
- Make mount flows idempotent: check status (control socket or /proc/mounts) before mounting
- Serialize mount operations with a lock so concurrent scripts/CI jobs don't race
- On retry-after-timeout, first verify whether the original mount actually succeeded
- Unmount explicitly before remounting when a fresh mount is genuinely required
When it happens
Trigger: Calling the mount operation for a mountpoint that already has a live lease and a healthy FUSE service answering ControlRequest::Status with access equal to the lease's access. Happens on duplicate mount commands, re-running a script, or two processes mounting the same path concurrently.
Common situations: CI or shell scripts that run 'mount' without checking current state; a teammate's/dev's earlier mount still active; automation retrying after a timeout though the first attempt actually succeeded.
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
- FUSE service status failed [{code}]: {message}
- exactly one of --as, --fleet, or --admin is required
- FUSE mount completed but is absent from the Linux mount tabl
- mount was issued to another acting principal
- detached FUSE service failed: {message}
AI-assisted analysis of astrid-runtime/astrid@affd8760f4 (2026-09-09).
Data as JSON: /api/errors/380f0bfbec3c21ec.
Report an issue: GitHub.