sxyazi/yazi · critical

failed to get current working directory

Error message

failed to get current working directory

What it means

Cwd::default() panics through expect when neither source yields a working directory: $PWD is unset or not absolute, and std::env::current_dir() (getcwd) returns an error. yazi bootstraps its process-wide CWD from an absolute $PWD first, then falls back to the OS; both failing means the OS cannot report a valid current directory.

Source

Thrown at yazi-fs/src/cwd.rs:26

pub static CWD: RoCell<Cwd> = RoCell::new();

pub struct Cwd(ArcSwap<UrlBuf>);

impl Deref for Cwd {
	type Target = ArcSwap<UrlBuf>;

	fn deref(&self) -> &Self::Target { &self.0 }
}

impl Default for Cwd {
	fn default() -> Self {
		let u = std::env::var_os("PWD")
			.map(PathBuf::from)
			.filter(|p| p.is_absolute())
			.map(clean_url)
			.or_else(|| current_dir().ok().map(UrlBuf::from))
			.expect("failed to get current working directory");

		Self(ArcSwap::new(Arc::new(u)))
	}
}

impl Cwd {
	pub fn path(&self) -> PathBuf { self.0.load().as_url().working_path().into_owned() }

	pub fn set(&self, url: &UrlBuf, callback: fn()) -> bool {
		if !url.is_absolute() {
			return false;
		} else if self.0.load().as_ref() == url {
			return false;
		}

		self.0.store(Arc::new(url.clone()));
		Self::sync_cwd(callback);

View on GitHub (pinned to 94abcfa92f)

Solutions

  1. cd to a live directory (cd /tmp) and relaunch — fixes the deleted-cwd case immediately
  2. Recreate the deleted directory (mkdir -p /old/cwd) so getcwd resolves again
  3. Export an absolute PWD before starting (cd "$PWD" in the shell, or env PWD="$PWD" yazi when PWD drifted)
  4. For embedders: std::env::set_current_dir("/") and set PWD to an absolute path before initializing yazi-fs
  5. Fix execute (x) permission on parent directories if the failure is EACCES

Example fix

// before: yazi-fs initialized while the process cwd was deleted
// -> panic "failed to get current working directory"

// after: pin a live directory before init
if std::env::current_dir().is_err() {
    std::env::set_var("PWD", "/"); // Cwd::default honors an absolute PWD first
    std::env::set_current_dir("/").ok();
}
Defensive patterns

Strategy: validation

Validate before calling

fn cwd_usable() -> bool {
    std::env::var_os("PWD").is_some_and(|p| std::path::Path::new(&p).is_absolute())
        || std::env::current_dir().is_ok()
}
// before initializing yazi-fs:
if !cwd_usable() {
    std::env::set_current_dir("/").ok();
    std::env::set_var("PWD", "/");
}

Try / catch

let cwd = std::panic::catch_unwind(Cwd::default)
    .unwrap_or_else(|_| Cwd(ArcSwap::new(Arc::new(UrlBuf::from("/"))))); // embedder-side last resort

Prevention

When it happens

Trigger: Initializing yazi-fs (CWD RoCell) with $PWD unset or relative while getcwd fails: the current directory was deleted (ENOENT, e.g. after git clean, docker rm of a bind mount, or a resurrected tmux session) or a parent directory lost execute permission (EACCES).

Common situations: Starting yazi from a shell whose cwd was removed by another process; tmux/screen session restore pointing at a gone directory; daemonized/service contexts with no cwd; wrappers that clear the environment including PWD.

Related errors


AI-assisted analysis of sxyazi/yazi@94abcfa92f (2026-08-16). Data as JSON: /api/errors/957568ed29d25164. Report an issue: GitHub.