sxyazi/yazi · error · io::Error
Not a local URL: {url}
Error message
Not a local URL: {url} What it means
LocalFs::new constructs a local filesystem entry from a URL, but only if `url.as_local()` yields a path. Non-local (e.g. SFTP) URLs are rejected with an InvalidInput error. It is the constructor-level equivalent of the open-time check in the local engine.
Source
Thrown at yazi-fs/src/engine/local/local.rs:75
#[inline]
async fn hard_link<P>(&self, to: P) -> io::Result<()>
where
P: DynPath,
{
let to = to.dyn_path().as_os()?;
tokio::fs::hard_link(self.path, to).await
}
#[inline]
async fn metadata(&self) -> io::Result<Cha> {
Ok(Cha::new(self.path.file_name().unwrap_or_default(), tokio::fs::metadata(self.path).await?))
}
#[inline]
async fn new<'b>(url: Url<'b>) -> io::Result<Self::Me<'b>> {
let path = url.as_local().ok_or_else(|| {
io::Error::new(io::ErrorKind::InvalidInput, format!("Not a local URL: {url}"))
})?;
Ok(Self::Me { url, path })
}
#[inline]
async fn read_dir(self) -> io::Result<Self::ReadDir> {
Ok(super::ReadDir(tokio::fs::read_dir(self.path).await?))
}
#[inline]
async fn read_link(&self) -> io::Result<PathBufDyn> {
Ok(tokio::fs::read_link(self.path).await?.into())
}
#[inline]
async fn remove_dir(&self) -> io::Result<()> { tokio::fs::remove_dir(self.path).await }
View on GitHub (pinned to 8ebf930f17)
Solutions
- Dispatch on the URL scheme first: only build LocalFs entries for local URLs; use Vfs/Sftp for remote ones.
- If the URL should be local, strip the remote auth / construct it with `Url::from` on a real filesystem path.
- Add an `url.as_local().is_some()` guard before calling the constructor.
Example fix
// before let file = LocalFs::File::new(url).await?; // after ensure!(url.as_local().is_some(), "use Vfs for remote URLs"); let file = LocalFs::File::new(url).await?;
Defensive patterns
Strategy: type-guard
Validate before calling
if url.as_local().is_none() { bail!("LocalFs::new requires a local URL"); } Type guard
fn is_local(url: &Url) -> bool { url.as_local().is_some() } Try / catch
// io::Error with InvalidInput kind
match LocalFs::File::new(url).await {
Err(e) if e.kind() == io::ErrorKind::InvalidInput => return Vfs::entry(url).await,
other => other.map_err(Into::into),
} Prevention
- Dispatch on URL scheme before choosing a filesystem engine.
- Never treat unknown schemes as local by default.
- Add unit checks that LocalFs is only constructed from path-backed URLs.
When it happens
Trigger: Creating a LocalFs entry (File/Folder via `new`) with a remote or otherwise non-local Url, such as a Unix URL carrying SFTP auth.
Common situations: Generic code that dispatches on URL kind but falls through to LocalFs for unknown schemes; copied code that assumed all URLs in a tab are local; hover/preview logic given a remote entry.
Understand the failure class
Background: "Invalid URL" / "URL cannot be empty": fix the malformed or missing URL behind request-construction failures — this error's family across 50 libraries.
Related errors
- Not a local URL: {url}
- Cannot read cache stamp: {e}
- Cannot write cache stamp: {e}
- Not a SFTP URL: {url}
- not a URL
AI-assisted analysis of sxyazi/yazi@8ebf930f17 (2026-09-09).
Data as JSON: /api/errors/8130c8622eb2dc14.
Report an issue: GitHub.