{"record":{"id":"0cab9eff17504c70","repo":"astrid-runtime/astrid","slug":"winfsp-service-control-endpoint-is-already-present","errorCode":null,"errorMessage":"WinFsp service control endpoint is already present","messagePattern":"WinFsp service control endpoint is already present","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/astrid-storage-provider-winfsp/src/win.rs","lineNumber":333,"sourceCode":"            .control_path\n            .components()\n            .any(|component| matches!(component, std::path::Component::ParentDir))\n        || launch.control_path != lease.resource_path.join(\"process-control.sock\")\n    {\n        bail!(\"WinFsp service control path is malformed\");\n    }\n    let control_parent = launch\n        .control_path\n        .parent()\n        .context(\"WinFsp service control path has no parent\")?;\n    platform_fs::validate_private_directory(control_parent)\n        .context(\"validate private WinFsp control parent\")?;\n    platform_fs::verify_no_redirects(&launch.control_path)\n        .context(\"reject redirected WinFsp control path\")?;\n    if local_transport::endpoint_is_present(&launch.control_path)\n        .context(\"inspect WinFsp service control endpoint\")?\n    {\n        bail!(\"WinFsp service control endpoint is already present\");\n    }\n    Ok(())\n}\n\nasync fn probe_callback(launch: &StorageProviderServiceLaunchV1) -> Result<()> {\n    let mut stream = local_transport::connect(&launch.lease.callback_path)\n        .await\n        .context(\"connect WinFsp lease callback\")?;\n    let request = StorageFilesystemRequestV2 {\n        protocol_version: STORAGE_FILESYSTEM_PROTOCOL_V2,\n        request_id: format!(\"winfsp-service-{}\", launch.lease.mount_id),\n        lease_token: launch.lease.lease_token.clone(),\n        operation: StorageFilesystemOperationV2::Stat {\n            path: String::new(),\n        },\n    };\n    let bytes = serde_json::to_vec(&request).context(\"encode WinFsp callback probe\")?;\n    let length = u32::try_from(bytes.len()).context(\"WinFsp callback probe is too large\")?;","sourceCodeStart":315,"sourceCodeEnd":351,"githubUrl":"https://github.com/astrid-runtime/astrid/blob/affd8760f44190dbdfbec23403f4c4b642c33112/crates/astrid-storage-provider-winfsp/src/win.rs#L315-L351","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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."],"exampleFix":"// before\nspawn_daemon(&lease, &launch)?; // fails: socket still present\n// after\nif local_transport::endpoint_is_present(&launch.control_path)? {\n    std::fs::remove_file(&launch.control_path)?; // stale socket from crashed daemon\n}\nspawn_daemon(&lease, &launch)?;","handlingStrategy":"validation","validationCode":"if local_transport::endpoint_is_present(&launch.control_path)? {\n    std::fs::remove_file(&launch.control_path)?; // only after confirming no live owner\n}","typeGuard":"fn endpoint_free(path: &Path) -> bool {\n    !path.exists()\n}","tryCatchPattern":"match service_main(&launch).await {\n    Err(e) if e.to_string().contains(\"already present\") => {\n        cleanup_stale_socket(&launch.control_path)?;\n        service_main(&launch).await\n    },\n    other => other,\n}","preventionTips":["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."],"tags":["socket-in-use","startup","winfsp"],"backgroundTag":"address-already-in-use","analyzedSha":"affd8760f44190dbdfbec23403f4c4b642c33112","analyzedAt":"2026-09-09T21:28:12.402Z","contentChangedAt":"2026-09-09T21:28:12.402Z","schemaVersion":2},"datasetVersion":"2026-09-17T15:17:12.973Z"}