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

daemon peer uid {peer_uid} does not match current uid {curre

Error message

daemon peer uid {peer_uid} does not match current uid {current_uid}

What it means

authorize_peer (endpoint.rs:539) runs on the daemon after accepting a Unix socket connection: it reads the peer's credentials via SO_PEERCRED (stream.peer_cred()) and requires peer uid == current euid. This PermissionDenied error means a process running as a different uid connected to the daemon socket; the daemon rejects it to prevent cross-user task/result injection.

Source

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

#[cfg(unix)]
fn set_private_socket_permissions(sock_path: &AbsoluteSystemPath) -> Result<(), std::io::Error> {
    use std::os::unix::fs::PermissionsExt;

    std::fs::set_permissions(
        sock_path.as_std_path(),
        std::fs::Permissions::from_mode(PRIVATE_SOCKET_MODE),
    )
}

#[cfg(unix)]
pub(crate) fn authorize_peer(stream: &tokio::net::UnixStream) -> Result<(), std::io::Error> {
    let peer_uid = stream.peer_cred()?.uid();
    let current_uid = current_uid();

    if peer_uid == current_uid {
        Ok(())
    } else {
        Err(std::io::Error::new(
            std::io::ErrorKind::PermissionDenied,
            format!("daemon peer uid {peer_uid} does not match current uid {current_uid}"),
        ))
    }
}

#[cfg(unix)]
struct AuthorizedUnixStream(tokio::net::UnixStream);

#[cfg(unix)]
impl AuthorizedUnixStream {
    fn project(self: std::pin::Pin<&mut Self>) -> std::pin::Pin<&mut tokio::net::UnixStream> {
        unsafe { self.map_unchecked_mut(|s| &mut s.0) }
    }
}

#[cfg(unix)]
impl AsyncRead for AuthorizedUnixStream {

View on GitHub (pinned to f9245100cf)

Solutions

  1. Run turbo as the same user that owns the daemon (no mixed sudo/su for the same cache paths)
  2. Unset TURBO daemon/socket env overrides when switching users: `env -u TURBO_DAEMON... `
  3. Restart a per-user daemon instead of sharing one socket across accounts

Example fix

# bash: don't inherit turbo env across users
sudo -E env -u TURBO_DAEMON_PID_FILE -u TURBO_DAEMON_SOCKET turbo run build
# or run the whole command as the daemon's user
Defensive patterns

Strategy: validation

Validate before calling

// client side: verify the socket belongs to your uid before talking to it
let m = std::fs::metadata(sock_path)?;
use std::os::unix::fs::MetadataExt;
if m.uid() != unsafe { libc::geteuid() } { anyhow::bail!("foreign daemon socket"); }

Try / catch

// daemon side this is by design; on the client treat PermissionDenied
// 'peer uid' as 'wrong daemon' — unset overrides and discover your own:
Err(e) if e.to_string().contains("peer uid") => { reset_turbo_env(); reconnect()?; }

Prevention

When it happens

Trigger: A different user on the same machine connects to your daemon socket — e.g. TURBO daemon env vars (socket path) leaked into another account's session via sudo/su, shared shell profiles, or a socket path on a shared volume used by multiple containers.

Common situations: `sudo -E` / `su` into another account while retaining TURBO_* env Multi-tenant CI boxes sharing HOME or XDG dirs Containers sharing a volume where the socket lives, with different uid mappings

Related errors


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