sxyazi/yazi · error · io::Error
directory {:?} is owned by uid {} but current uid is {}
Error message
directory {:?} is owned by uid {} but current uid is {} What it means
`create_owned_dir_blocking` (yazi-fs/src/fns.rs:108) creates a directory with mode 0o700, opens it with `O_DIRECTORY|O_NOFOLLOW`, `fstat`s it, and rejects it when `st_uid` differs from the current effective uid (`ErrorKind::PermissionDenied`). This is a security check: a 0o700 private dir owned by someone else would let that owner read data the current process writes there.
Source
Thrown at yazi-fs/src/fns.rs:108
{
use std::{fs::{DirBuilder, OpenOptions}, mem, os::unix::{fs::{DirBuilderExt, OpenOptionsExt}, io::AsRawFd}};
use libc::{O_DIRECTORY, O_NOFOLLOW};
use uzers::Users;
use yazi_shared::USERS_CACHE;
DirBuilder::new().mode(0o700).recursive(true).create(p)?;
let dir = OpenOptions::new().read(true).custom_flags(O_DIRECTORY | O_NOFOLLOW).open(p)?;
let mut stat: libc::stat = unsafe { mem::zeroed() };
if unsafe { libc::fstat(dir.as_raw_fd(), &mut stat) } != 0 {
return Err(io::Error::last_os_error());
}
// Reject directories not owned by the current user.
let uid = USERS_CACHE.get_current_uid();
if stat.st_uid != uid {
return Err(io::Error::new(
io::ErrorKind::PermissionDenied,
format!("directory {:?} is owned by uid {} but current uid is {}", p, stat.st_uid, uid),
));
}
// Enforce mode 0o700 via the fd.
if unsafe { libc::fchmod(dir.as_raw_fd(), 0o700) } != 0 {
return Err(io::Error::last_os_error());
}
Ok(())
}
#[cfg(not(unix))]
{
std::fs::DirBuilder::new().recursive(true).create(p)
}
}
View on GitHub (pinned to 94abcfa92f)
Solutions
- Remove the offending directory and let the current user recreate it: `sudo rm -rf /run/user/1000/<dir>` (or the path shown in the message), then retry.
- Fix ownership instead of deleting: `sudo chown -R $(id -u):$(id -g) <dir>`.
- Always run the app as the same user that owns its runtime dirs; never launch it with `sudo` for normal use.
- Point the runtime dir at a per-user location (e.g. under `$XDG_RUNTIME_DIR`) that cannot be pre-created by others.
Example fix
# before # dir was created by root earlier; app now runs as uid 1000 -> PermissionDenied # after sudo rm -rf /run/user/1000/yazi # restart the app; it recreates the dir owned by uid 1000 with mode 0700
Defensive patterns
Strategy: validation
Validate before calling
use uzers::Users;
use yazi_shared::USERS_CACHE;
fn owned_by_current_user(p: &std::path::Path) -> std::io::Result<bool> {
use std::os::unix::fs::MetadataExt;
let uid = USERS_CACHE.get_current_uid();
Ok(std::fs::metadata(p)?.uid() == uid)
}
if !owned_by_current_user(p)? { /* fix ownership before create_owned_dir */ } Try / catch
match create_owned_dir(p).await {
Ok(()) => {}
Err(e) if e.kind() == io::ErrorKind::PermissionDenied => {
// surface path + current uid; instruct chown/rm of the foreign-owned dir
}
Err(e) => return Err(e),
} Prevention
- Never run the app under sudo/root for normal use; runtime dirs then become root-owned.
- Keep per-process state under $XDG_RUNTIME_DIR, which is uid-scoped by design.
- On first launch failure with PermissionDenied, check `stat -c %u <dir>` before retrying.
When it happens
Trigger: The directory already exists (pre-created by root, another user, or an earlier run under a different uid) and `create` succeeds as a no-op; the subsequent fstat then finds a foreign owner. Typical for runtime/socket/cache dirs under `/run/user/<uid>` or `$XDG_RUNTIME_DIR`.
Common situations: Running yazi once under `sudo` and again as the normal user (root-owned dir left behind); container/user-namespace builds where uid mapping shifts; a shared or restored home where the runtime dir kept its old owner.
Related errors
AI-assisted analysis of sxyazi/yazi@94abcfa92f (2026-08-16).
Data as JSON: /api/errors/be13377a98ab2951.
Report an issue: GitHub.