denoland/deno · error · AnyError
temporary directory ancestor '{}' is owned by uid {}, not cu
Error message
temporary directory ancestor '{}' is owned by uid {}, not current uid {} or root What it means
Before creating its temp node_modules root (`<tmp>/deno_nm`), Deno canonicalizes the temp dir and walks every ancestor, opening each with O_NOFOLLOW|O_DIRECTORY (`ensure_secure_temp_parent`, cli/util/temp.rs). If any ancestor's owner uid is neither the current effective uid nor root (0), Deno refuses to proceed — a directory another user controls could be swapped or manipulated underneath Deno's temp files.
Source
Thrown at cli/util/temp.rs:131
}
ensure_secure_temp_dir(path)
}
#[cfg(unix)]
fn ensure_secure_temp_parent(path: &Path) -> Result<(), AnyError> {
use std::os::unix::fs::MetadataExt;
use std::os::unix::fs::OpenOptionsExt;
// SAFETY: geteuid has no preconditions.
let current_uid = unsafe { libc::geteuid() };
for ancestor in path.ancestors() {
let dir = std::fs::OpenOptions::new()
.read(true)
.custom_flags(libc::O_NOFOLLOW | libc::O_DIRECTORY)
.open(ancestor)?;
let metadata = dir.metadata()?;
if metadata.uid() != current_uid && metadata.uid() != 0 {
bail!(
"temporary directory ancestor '{}' is owned by uid {}, not current uid {} or root",
ancestor.display(),
metadata.uid(),
current_uid
);
}
let mode = metadata.mode();
if mode & 0o022 != 0 && mode & 0o1000 == 0 {
bail!(
"temporary directory ancestor '{}' is writable by other users without the sticky bit",
ancestor.display()
);
}
}
Ok(())
}
#[cfg(not(unix))]View on GitHub (pinned to 9ad36f7a2c)
Solutions
- Point TMPDIR at a directory you own: `mkdir -p ~/tmp && export TMPDIR=~/tmp`.
- Or unset TMPDIR and use the system /tmp, which is root-owned with the sticky bit and passes the walk.
- If sharing is intended, have the admin `chown` the ancestor to your user (or a common uid).
- Avoid TMPDIRs under other users' home directories or foreign-uid volumes.
Example fix
# before export TMPDIR=/srv/shared/tmp # owned by uid 1000, you are uid 1001 deno install # error: temporary directory ancestor '/srv/shared/tmp' is owned by uid 1000, not current uid 1001 # after mkdir -p "$HOME/tmp" && export TMPDIR="$HOME/tmp" deno install
Defensive patterns
Strategy: validation
Validate before calling
# pre-check every TMPDIR ancestor for foreign non-root ownership
d="$(cd "${TMPDIR:-/tmp}" && pwd -P)"; uid="$(id -u)"
while [ "$d" != "/" ]; do
o="$(stat -c %u "$d" 2>/dev/null || echo 0)"
if [ "$o" != "$uid" ] && [ "$o" != "0" ]; then
echo "insecure temp ancestor: $d (uid $o)"
fi
d="$(dirname "$d")"
done Prevention
- Default to the system /tmp or a per-user TMPDIR under your own home.
- Never set TMPDIR under another user's home or a foreign-uid shared volume.
- In containers, give each uid its own temp path instead of sharing one.
When it happens
Trigger: TMPDIR/TMP pointing under a directory owned by a different non-root user: `TMPDIR=/home/otheruser/tmp` while running as your uid, a shared volume like /mnt/data/tmp chowned to a service account, or NFS mounts with uid mapping showing foreign ownership. Hit on the first `deno install`/run that needs the temp node_modules dir.
Common situations: Containers with TMPDIR set to an app-owned path; NFS/network mounts with idmapping; multi-user servers sharing scratch directories; sudo/user transition flows where the effective uid differs from the directory owner.
Related errors
- temporary directory ancestor '{}' is writable by other users
- '{}' is owned by uid {}, not current uid {}
- You don't have write permission to {} because it's owned by
- '{}' is writable or readable by other users
- Native addon cache path '{}' is not a private directory
AI-assisted analysis of denoland/deno@9ad36f7a2c (2026-08-20).
Data as JSON: /api/errors/747af3220782dd3b.
Report an issue: GitHub.