vercel/turborepo · error · std::io::Error

daemon socket path is owned by another user: {path}

Error message

daemon socket path is owned by another user: {path}

What it means

During Windows daemon startup, ensure_current_user_owns_path (endpoint.rs:241) reads the path's owner SID with GetNamedSecurityInfoW and compares it to the current user's SID with EqualSid. A mismatch produces this PermissionDenied error: the directory that will host the daemon socket belongs to a different account, so turbo refuses to run there to stop another user from controlling the pipe directory.

Source

Thrown at crates/turborepo-daemon/src/endpoint.rs:241

                ConvertSidToStringSidW, ConvertStringSecurityDescriptorToSecurityDescriptorW,
                GetNamedSecurityInfoW, SetNamedSecurityInfoW, SDDL_REVISION_1, SE_FILE_OBJECT,
            },
            EqualSid, GetSecurityDescriptorDacl, GetTokenInformation, TokenUser, ACL,
            DACL_SECURITY_INFORMATION, OWNER_SECURITY_INFORMATION,
            PROTECTED_DACL_SECURITY_INFORMATION, PSECURITY_DESCRIPTOR, PSID, TOKEN_QUERY,
            TOKEN_USER,
        },
        System::Threading::{GetCurrentProcess, OpenProcessToken},
    };

    pub fn ensure_current_user_owns_path(path: &AbsoluteSystemPath) -> Result<(), std::io::Error> {
        let current_user = current_user_sid()?;
        let owner = path_owner_sid(path)?;

        if unsafe { EqualSid(current_user.as_ptr(), owner.as_ptr()) } != 0 {
            Ok(())
        } else {
            Err(std::io::Error::new(
                std::io::ErrorKind::PermissionDenied,
                format!("daemon socket path is owned by another user: {path}"),
            ))
        }
    }

    pub fn set_owner_only_dacl(
        path: &AbsoluteSystemPath,
        inherit_to_children: bool,
    ) -> Result<(), std::io::Error> {
        let current_user = current_user_sid()?;
        let current_user = sid_to_string(current_user.as_ptr())?;
        let inherit_flags = if inherit_to_children { "OICI" } else { "" };
        let sddl = format!("D:P(A;{inherit_flags};FA;;;{current_user})");
        let sddl = wide_null(OsStr::new(&sddl));

        let mut descriptor = ptr::null_mut();
        if unsafe {

View on GitHub (pinned to f9245100cf)

Solutions

  1. Delete the stale daemon directory shown in the message (usually under %TEMP%\turborepo or the user profile) so the current user recreates it
  2. Take ownership of the existing directory: `takeown /f <path> /r` then `icacls <path> /setowner <you>`
  3. Always run turbo/daemon as the same Windows account that owns those dirs

Example fix

:: stop daemon, remove stale dir, restart
turbo daemon stop
rmdir /s /q "%TEMP%\turborepo"
turbo daemon start
Defensive patterns

Strategy: fallback

Validate before calling

// Windows: check ownership before starting the daemon
fn owned_by_me(path: &Path) -> bool {
    // use windows_acl or icacls exit code in a pre-step
    std::process::Command::new("icacls").arg(path).status().map(|s| s.success()).unwrap_or(false)
}

Try / catch

// on PermissionDenied 'owned by another user': drop the dir and retry once
match start_daemon() {
    Err(e) if e.kind() == std::io::ErrorKind::PermissionDenied && e.to_string().contains("owned by another user") => {
        std::fs::remove_dir_all(daemon_dir).ok();
        start_daemon()?; // retry once after recreation
    }
    r => r,
}

Prevention

When it happens

Trigger: Daemon start where the socket dir (typically under %TEMP% or the user profile) was created by a different Windows account — admin provisioning, `runas`/service-account runs, or a profile restored from another machine.

Common situations: Machine shared between accounts and turbo daemon dirs created by the first one Running the daemon as a service/scheduled task under SYSTEM after using it interactively Profile migration/cloning keeping old ownership

Related errors


AI-assisted analysis of vercel/turborepo@f9245100cf (2026-08-17). Data as JSON: /api/errors/1609a8ee80be0217. Report an issue: GitHub.