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
- Ensure the target URL includes a filename component after the root (e.g. `/file.txt`, not `/`)
- Check the parent with `url.parent()` before invoking `mgr:create` and bail with your own message if None
- If creating at a scheme root is genuinely needed, pick a concrete parent directory first or use a different API that supports directory creation
- 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
- Always join a filename onto a directory URL before calling create
- Guard with url.parent().is_some() in plugin code
- Never hardcode scheme-root targets like "/" in keymaps
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
- Target URL must be absolute
- Failed to join new name with parent directory
- InvalidData
- Failed to join new name with CWD
- atime not available
AI-assisted analysis of sxyazi/yazi@5f901b886b (2026-09-02).
Data as JSON: /api/errors/9f10368508b855ec.
Report an issue: GitHub.