vercel/turborepo · error · std::io::Error
daemon socket parent is owned by another user: {socket_dir}
Error message
daemon socket parent is owned by another user: {socket_dir} What it means
secure_unix_dir (endpoint.rs:504) compares metadata.uid() from symlink_metadata against libc::geteuid(); a mismatch yields this PermissionDenied error. The daemon hardens both the socket dir and its parent, so it refuses when either directory is owned by another uid — otherwise a different user could pre-create or rewrite those directories and hijack the socket.
Source
Thrown at crates/turborepo-daemon/src/endpoint.rs:504
#[cfg(unix)]
fn secure_unix_dir(socket_dir: &AbsoluteSystemPath) -> Result<(), std::io::Error> {
use std::os::unix::fs::{DirBuilderExt, MetadataExt, PermissionsExt};
std::fs::DirBuilder::new()
.recursive(true)
.mode(PRIVATE_DIR_MODE)
.create(socket_dir.as_std_path())?;
let metadata = std::fs::symlink_metadata(socket_dir.as_std_path())?;
if !metadata.file_type().is_dir() {
return Err(std::io::Error::new(
std::io::ErrorKind::PermissionDenied,
format!("daemon socket parent is not a directory: {socket_dir}"),
));
}
if metadata.uid() != current_uid() {
return Err(std::io::Error::new(
std::io::ErrorKind::PermissionDenied,
format!("daemon socket parent is owned by another user: {socket_dir}"),
));
}
let mode = metadata.permissions().mode() & 0o777;
if mode != PRIVATE_DIR_MODE {
std::fs::set_permissions(
socket_dir.as_std_path(),
std::fs::Permissions::from_mode(PRIVATE_DIR_MODE),
)?;
}
Ok(())
}
#[cfg(unix)]
fn set_private_socket_permissions(sock_path: &AbsoluteSystemPath) -> Result<(), std::io::Error> {View on GitHub (pinned to f9245100cf)
Solutions
- Remove the offending directory shown in the message with sufficient privileges (e.g. `sudo rm -rf <path>`) so your uid recreates it
- Never mix uids for the same HOME/cache paths; run turbo and daemon as the same user
- In containers, keep the runtime dir on a per-uid path (XDG_RUNTIME_DIR) instead of a shared one
Example fix
# bash: clear root-owned daemon dir, restart as yourself sudo rm -rf ~/.cache/turborepo turbo daemon restart
Defensive patterns
Strategy: fallback
Validate before calling
// unix: pre-check ownership of socket dir and its parent
let m = std::fs::symlink_metadata(dir)?;
use std::os::unix::fs::MetadataExt;
if m.uid() != unsafe { libc::geteuid() } {
anyhow::bail!("{dir} owned by uid {}, refusing to start", m.uid());
} Try / catch
// on ownership mismatch: remove and let the daemon recreate
Err(e) if e.kind() == std::io::ErrorKind::PermissionDenied
&& e.to_string().contains("owned by another user") => {
// may need elevated removal if root-owned
std::process::Command::new("sudo").arg("rm").arg("-rf").arg(dir).status()?;
daemon_start()?;
} Prevention
- Never run turbo under sudo against your user HOME/cache paths
- Use XDG_RUNTIME_DIR (per-uid) for sockets on multi-user machines
When it happens
Trigger: Daemon start when the socket dir or its parent was created by another uid: previously running turbo under sudo, shared HOME between accounts, containers with mismatched uid maps, or root-created leftovers in /tmp-adjacent paths.
Common situations: `sudo turbo ...` once created root-owned ~/.cache/turborepo Shared CI machines where another user's env pointed at the same paths Volume-mounted home dirs with shifted uids
Related errors
- daemon socket path is owned by another user: {path}
- daemon socket path did not have an owner SID
- daemon peer uid {peer_uid} does not match current uid {curre
- owner-only security descriptor did not contain a DACL
- daemon socket parent is not a directory: {socket_dir}
AI-assisted analysis of vercel/turborepo@f9245100cf (2026-08-17).
Data as JSON: /api/errors/773f6f9bf76bd3b8.
Report an issue: GitHub.