denoland/deno · error

Native addon cache directory '{}' is not owned by the curren

Error message

Native addon cache directory '{}' is not owned by the current user

What it means

Unix-only ownership check in Deno's native addon cache validation: fs::symlink_metadata().uid() must equal the current process uid, or the directory is rejected with ErrorKind::PermissionDenied. A cache directory owned by another user could be pre-populated or tampered with, so Deno refuses it. This message escaping also implies the fresh-tempdir fallback failed (e.g. the temp filesystem reports on-disk uids that do not match the process uid).

Source

Thrown at ext/rt_helper/lib.rs:261

  if metadata.file_type().is_symlink() || !metadata.is_dir() {
    return Err(std::io::Error::new(
      ErrorKind::PermissionDenied,
      format!(
        "Native addon cache path '{}' is not a private directory",
        path.display()
      ),
    ));
  }

  // Windows temp directories are normally per-user; Unix additionally
  // enforces ownership and mode here.
  #[cfg(unix)]
  {
    use std::os::unix::fs::MetadataExt;
    use std::os::unix::fs::PermissionsExt;

    if metadata.uid() != current_uid() {
      return Err(std::io::Error::new(
        ErrorKind::PermissionDenied,
        format!(
          "Native addon cache directory '{}' is not owned by the current user",
          path.display()
        ),
      ));
    }

    if metadata.permissions().mode() & 0o777 != 0o700 {
      fs::set_permissions(path, fs::Permissions::from_mode(0o700))?;
      let metadata = fs::symlink_metadata(path)?;
      if metadata.permissions().mode() & 0o777 != 0o700 {
        return Err(std::io::Error::new(
          ErrorKind::PermissionDenied,
          format!(
            "Native addon cache directory '{}' is not private",
            path.display()
          ),

View on GitHub (pinned to 9ad36f7a2c)

Solutions

  1. Remove the foreign-owned cache dir: sudo rm -rf "$TMPDIR"/deno-native-addon-cache (or the reported path), then rerun as the intended user.
  2. Point TMPDIR at a directory owned by the current uid: export TMPDIR=$(mktemp -d).
  3. In containers, run as a consistent uid (USER directive) and avoid uid-remapped mounts for the temp dir.
  4. Never mix sudo and non-sudo runs against the same temp/cache location.

Example fix

# before
sudo deno run app.ts   # creates root-owned cache dir
 deno run app.ts       # PermissionDenied: not owned by the current user

# after
sudo rm -rf "$TMPDIR"/deno-native-addon-cache
deno run app.ts
Defensive patterns

Strategy: validation

Validate before calling

import { statSync } from "node:fs";
import { tmpdir } from "node:os";
const t = process.env.TMPDIR ?? tmpdir();
const st = statSync(t, { throwIfNoEntry: false });
if (st && process.getuid && st.uid !== process.getuid()) throw new Error(`TMPDIR owned by uid ${st.uid}, running as ${process.getuid()} — pick a per-user temp dir`);

Try / catch

try { await run(); } catch (e) { if (/not owned by the current user/.test(String(e))) throw new Error(`stale cache dir with foreign owner under TMPDIR — remove it and rerun: rm -rf ${t}/deno-native-addon-cache`); throw e; }

Prevention

When it happens

Trigger: The cache dir under TMPDIR was created by another uid (earlier sudo run, image build step, other user on a shared box), or the temp filesystem is an idmapped/userns mount where the on-disk uid never matches the in-namespace current uid, so even a freshly created fallback dir fails the equality check.

Common situations: Running deno once with sudo then again as a normal user; rootless containers with uid remapping; bind-mounted volumes from a different uid; CI caches restored with preserved ownership; shared multi-user machines.

Related errors


AI-assisted analysis of denoland/deno@9ad36f7a2c (2026-08-20). Data as JSON: /api/errors/61dd29bcac8cff9d. Report an issue: GitHub.