sxyazi/yazi · error

Cannot create file at root

Error message

Cannot create file at root

What it means

Yazi's file-creation actor refuses to create a regular file when the requested URL has no parent directory, i.e. the target is the virtual root of a URL scheme. Creating a file requires a parent to exist (and possibly a stale file to be removed), so an anchorless path is treated as an invalid destination rather than attempted. It is thrown via `bail!` inside `mgr:create`'s `r#do` implementation.

Source

Thrown at yazi-actor/src/mgr/create.rs:74

impl Create {
	async fn r#do(new: UrlBuf, dir: bool) -> Result<()> {
		let _permit = WATCHER.acquire().await.unwrap();

		if dir {
			engine::create_dir_all(&new).await?;
		} else if let Ok(real) = engine::casefold(&new).await
			&& let Some((trail, key)) = real.pair()
		{
			ok_or_not_found!(engine::remove_file(&new).await);
			FilesOp::Deleting(trail.into(), [key.into()].into()).emit();
			engine::create(&new).await?;
		} else if let Some(parent) = new.parent() {
			engine::create_dir_all(parent).await.ok();
			ok_or_not_found!(engine::remove_file(&new).await);
			engine::create(&new).await?;
		} else {
			bail!("Cannot create file at root");
		}

		if let Ok(real) = engine::casefold(&new).await
			&& let Some((trail, key)) = real.pair()
		{
			let file = engine::file(&real).await?;
			FilesOp::Upserting(trail.into(), [(key.into(), file)].into()).emit();
			MgrProxy::reveal(&real);
		}

		Ok(())
	}
}

View on GitHub (pinned to 5f901b886b)

Solutions

  1. Ensure the target URL includes a filename component after the root (e.g. `/file.txt`, not `/`)
  2. Check the parent with `url.parent()` before invoking `mgr:create` and bail with your own message if None
  3. If creating at a scheme root is genuinely needed, pick a concrete parent directory first or use a different API that supports directory creation
  4. Inspect any custom plugin/keymap that computes the create target and fix the path join logic

Example fix

// before
act!(mgr:create, cx, url)  // url == "/" -> bails
// after
if url.parent().is_none() {
    anyhow::bail!("provide a file name, not a scheme root");
}
act!(mgr:create, cx, url)
Defensive patterns

Strategy: validation

Validate before calling

fn can_create_at(url: &Url) -> bool {
    url.parent().is_some()
}
// call only if can_create_at(&target) else surface a user message

Type guard

fn has_parent(url: &Url) -> bool {
    url.parent().is_some()
}

Try / catch

match mgr_create(cx, url).await {
    Ok(()) => {},
    Err(e) if e.to_string().contains("Cannot create file at root") => {
        notify::warn("Pick a real directory, not the scheme root");
    }
    Err(e) => return Err(e),
}

Prevention

When it happens

Trigger: Calling `mgr:create` (the `create` plugin/command) with a target URL whose `parent()` is None — for example an empty path or a bare scheme root like `/` or `sftp://host/` — so the code falls into the final `else` branch.

Common situations: A user runs `:create` while in the root directory of a mount/scheme and yazi resolves the new file path to the root itself; custom plugins or keymaps that pass a computed URL to `mgr:create` without ensuring a filename component exists; misconfigured plugin snippets that join segments incorrectly.

Related errors


AI-assisted analysis of sxyazi/yazi@5f901b886b (2026-09-02). Data as JSON: /api/errors/9f10368508b855ec. Report an issue: GitHub.