sxyazi/yazi · critical
URN cannot be longer than URI
Error message
URN cannot be longer than URI
What it means
`Loc::with` builds a `Loc` — a URL with cached byte offsets marking the URI (ancestors tail) and URN (file-name tail) boundaries within the path. The invariant `urn <= uri` must hold: the URN region is always a suffix-subset of the URI region. Passing `urn > uri` violates that invariant and bails with "URN cannot be longer than URI".
Source
Thrown at yazi-shared/src/loc/loc.rs:211
)
}
}
#[inline]
pub(crate) fn urn(self) -> P {
unsafe {
P::from_encoded_bytes_unchecked(
self.inner.as_encoded_bytes().get_unchecked(self.inner.len() - self.urn..),
)
}
}
pub(crate) fn with<T>(path: T, uri: usize, urn: usize) -> Result<Self>
where
T: PathView<'p, P>,
{
if urn > uri {
bail!("URN cannot be longer than URI");
}
let mut loc = Self::bare(path);
if uri == 0 {
(loc.uri, loc.urn) = (0, 0);
return Ok(loc);
} else if urn == 0 {
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();
}View on GitHub (pinned to 8ebf930f17)
Solutions
- Swap or fix the arguments so `urn <= uri` at the call site.
- Recompute the component counts from the same path value passed to `with`.
- If only the file-name tail is needed, pass `urn == uri` (e.g. `with(path, n, n)`), never a larger urn.
- Add a debug_assert or pre-check on the counts before the call during development.
Example fix
// before let loc = Loc::with(url, uri_components, urn_components); // urn_components > uri_components // after let urn_components = urn_components.min(uri_components); let loc = Loc::with(url, uri_components, urn_components)?;
Defensive patterns
Strategy: validation
Validate before calling
fn safe_with(path: &Url, uri: usize, urn: usize) -> anyhow::Result<Loc> {
anyhow::ensure!(urn <= uri, "urn ({urn}) must be <= uri ({uri})");
Loc::with(path, uri, urn)
} Try / catch
let loc = Loc::with(url, uri, urn.min(uri))
.wrap_err("building Loc for hover")?; Prevention
- Always clamp urn to uri at the call site.
- Derive both counts from the same path value in the same expression.
- Check argument order (path, uri, urn) — swapping them triggers this.
- Add a debug_assert!(urn <= uri) near hot hover/parent paths.
When it happens
Trigger: Calling `Loc::with(path, uri, urn)` (crate-internal, via constructors like hover/parent derivations) with a urn component count strictly greater than the uri component count, e.g. `with(path, 1, 2)`.
Common situations: Bugs in code computing how many components to strip for urn vs uri (off-by-one or swapped arguments); passing a count derived from one path to a `with` call on a different, shorter path; internal refactors of hover/spot logic that misorder the two counters.
Related errors
- URI exceeds the entire URL
- URN cannot include a root directory
- not a URL
- not a number
- argument not found: {:?}
AI-assisted analysis of sxyazi/yazi@8ebf930f17 (2026-09-02).
Data as JSON: /api/errors/701eadbd9de1badc.
Report an issue: GitHub.