sxyazi/yazi · critical

URN cannot include a root directory

Error message

URN cannot include a root directory

What it means

After computing the URI/URN boundaries, `Loc::with` verifies that the resulting URN (the file-name tail slice) does not contain a root directory component. A URN is meant to be the final, relative name portion of the URL; if the requested urn/uri counts pull in the filesystem root (e.g. on a path whose whole body was consumed), it bails with "URN cannot include a root directory".

Source

Thrown at yazi-shared/src/loc/loc.rs:237

			loc.urn = 0;
		}

		let mut it = loc.inner.components();
		for i in 1..=uri {
			if it.next_back().is_none() {
				bail!("URI exceeds the entire URL");
			}
			if i == urn {
				loc.urn = loc.strip_prefix(it.clone()).unwrap().len();
			}
			if i == uri {
				loc.uri = loc.strip_prefix(it).unwrap().len();
				break;
			}
		}

		if loc.urn().has_root() {
			bail!("URN cannot include a root directory");
		}
		Ok(loc)
	}

	pub(crate) fn zeroed<T>(path: T) -> Self
	where
		T: PathView<'p, P>,
	{
		let mut loc = Self::bare(path);
		(loc.uri, loc.urn) = (0, 0);
		loc
	}
}

#[cfg(test)]
mod tests {
	use std::path::Path;

View on GitHub (pinned to 8ebf930f17)

Solutions

  1. Reduce the urn (and uri) counts so the URN tail stops below the root component.
  2. Exclude the root when counting components for urn/uri derivation.
  3. Use `Loc::zeroed` or the bare constructor when you want no urn/uri split for near-root paths.
  4. Guard the call: if the path's component count equals the desired urn count on an absolute path, decrement or zero it.

Example fix

// before
let loc = Loc::with(url, comps, comps)?; // comps includes root -> URN is "/..."
// after
let comps = url.components().count();
let usable = if url.has_root() { comps - 1 } else { comps };
let loc = Loc::with(url, usable.max(1), usable.min(usable))?;
Defensive patterns

Strategy: validation

Validate before calling

fn usable_components(url: &Url) -> usize {
    let n = url.components().count();
    if url.components().has_root() { n - 1 } else { n }
}

Try / catch

let n = usable_components(&url);
let loc = if n == 0 { Loc::zeroed(&url) } else { Loc::with(&url, n, n)? };

Prevention

When it happens

Trigger: Calling `Loc::with` with component counts large enough that the URN slice begins at the path root — e.g. urn counts covering all components of `/file` so `loc.urn()` starts at `/`; applying deep-path counts to a path one component short of exhausting to the root.

Common situations: Computing urn/uri counts on absolute paths without excluding the root component; passing a count from a path like `/a/b/c` to a path like `/a`; hover or spot code that walks to the topmost ancestor of a root-level file.

Related errors


AI-assisted analysis of sxyazi/yazi@8ebf930f17 (2026-09-02). Data as JSON: /api/errors/76d71d31b9a7b23f. Report an issue: GitHub.