astrid-runtime/astrid · error
WinFsp service control endpoint is already present
Error message
WinFsp service control endpoint is already present
What it means
Before starting the private service, validate_service_launch checks that no stale control endpoint (Unix-domain-style socket) already exists at control_path. If local_transport::endpoint_is_present reports the path is occupied, startup is aborted to avoid binding conflicts or hijacking a pre-existing socket.
Solutions
- Stop the existing daemon that owns the socket, or delete the stale process-control.sock file, then relaunch.
- Check for a running duplicate instance (ps / process manager) and use it instead of spawning a new one.
- Ensure shutdown paths unlink the control endpoint so a clean restart leaves no file behind.
Example fix
// before
spawn_daemon(&lease, &launch)?; // fails: socket still present
// after
if local_transport::endpoint_is_present(&launch.control_path)? {
std::fs::remove_file(&launch.control_path)?; // stale socket from crashed daemon
}
spawn_daemon(&lease, &launch)?; Defensive patterns
Strategy: validation
Validate before calling
if local_transport::endpoint_is_present(&launch.control_path)? {
std::fs::remove_file(&launch.control_path)?; // only after confirming no live owner
} Type guard
fn endpoint_free(path: &Path) -> bool {
!path.exists()
} Try / catch
match service_main(&launch).await {
Err(e) if e.to_string().contains("already present") => {
cleanup_stale_socket(&launch.control_path)?;
service_main(&launch).await
},
other => other,
} Prevention
- Use a process manager that reliably terminates and cleans up old daemons.
- Unlink the control socket in the daemon's shutdown/crash handlers.
- Run one daemon per lease resource path; add a lockfile to prevent double starts.
- Clear socket files in entrypoint scripts for containers with persistent volumes.
When it happens
Trigger: service_main -> validate_service_launch when a previous daemon crashed without cleaning up its socket, or when two instances are launched with the same lease resource path.
Common situations: Killed daemon leaving an orphaned process-control.sock; double-starting the mount service; running a second mount for the same resource concurrently; container restarts with a persistent volume that kept the socket file.
Related errors
- WinFsp daemon exited immediately after readiness
- build WinFsp callback filesystem
- candidate generation for
- Daemon exited prematurely
- Daemon is still starting after
AI-assisted analysis of astrid-runtime/astrid@affd8760f4 (2026-09-09).
Data as JSON: /api/errors/0cab9eff17504c70.
Report an issue: GitHub.
Appendix: source
Thrown at crates/astrid-storage-provider-winfsp/src/win.rs:333
.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")?;
if local_transport::endpoint_is_present(&launch.control_path)
.context("inspect WinFsp service control endpoint")?
{
bail!("WinFsp service control endpoint is already present");
}
Ok(())
}
async fn probe_callback(launch: &StorageProviderServiceLaunchV1) -> Result<()> {
let mut stream = local_transport::connect(&launch.lease.callback_path)
.await
.context("connect WinFsp lease callback")?;
let request = StorageFilesystemRequestV2 {
protocol_version: STORAGE_FILESYSTEM_PROTOCOL_V2,
request_id: format!("winfsp-service-{}", launch.lease.mount_id),
lease_token: launch.lease.lease_token.clone(),
operation: StorageFilesystemOperationV2::Stat {
path: String::new(),
},
};
let bytes = serde_json::to_vec(&request).context("encode WinFsp callback probe")?;
let length = u32::try_from(bytes.len()).context("WinFsp callback probe is too large")?;View on GitHub (pinned to affd8760f4)