sxyazi/yazi · error · io::Error

Not a local URL

Error message

Not a local URL: {url}

What it means

Local file operations in yazi-fs's local engine require a URL that resolves to a local filesystem path (`url.as_local()`). When given a remote (Sftp/other-scheme) or non-local URL, `open` returns an InvalidInput io::Error naming the URL. This is a guard against using the local file engine for non-local locations.

Solutions

  1. Check `url.as_local().is_some()` (or the URL scheme) before opening and route remote URLs to the appropriate VFS engine instead.
  2. If the file should be local, correct its construction so the URL has no remote auth component.
  3. For remote reads, use the SFTP engine (yazi-vfs) or download to a local temporary path first.

Example fix

// before
LocalFile::open(url).await?; // may be remote
// after
if let Some(path) = url.as_local() {
    LocalFile::open(path).await?;
} else {
    Vfs::open(url).await?;
}
Defensive patterns

Strategy: type-guard

Validate before calling

if url.as_local().is_none() { /* route to Vfs/Sftp engine instead */ }

Type guard

fn local_path(url: &Url) -> Option<&Path> { url.as_local() }

Try / catch

// io::Error with InvalidInput kind
match LocalFile::open(url).await {
    Err(e) if e.kind() == io::ErrorKind::InvalidInput => route_to_vfs(url).await,
    other => other?,
}

Prevention

When it happens

Trigger: Calling the local file open API (File::open via LocalFs demand) with a Url that is not a local scheme, e.g. a Unix-with-auth (SFTP) URL.

Common situations: Plugin/task code holding a URL from a remote tab and passing it to a local-file API; forgetting to route remote URLs through the VFS/SFTP engine; mixing Mgr entries from different scheme tabs.

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


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

Appendix: source

Thrown at yazi-fs/src/engine/local/demand.rs:44

	fn create(&mut self, create: bool) -> &mut Self {
		self.0.create(create);
		self
	}

	fn create_new(&mut self, create_new: bool) -> &mut Self {
		self.0.create_new(create_new);
		self
	}

	async fn open<U>(&self, url: U) -> io::Result<Self::File>
	where
		U: AsUrl,
	{
		let url = url.as_url();
		if let Some(path) = url.as_local() {
			self.0.open(path).await
		} else {
			Err(io::Error::new(io::ErrorKind::InvalidInput, format!("Not a local URL: {url}")))
		}
	}

	fn read(&mut self, read: bool) -> &mut Self {
		self.0.read(read);
		self
	}

	fn truncate(&mut self, truncate: bool) -> &mut Self {
		self.0.truncate(truncate);
		self
	}

	fn write(&mut self, write: bool) -> &mut Self {
		self.0.write(write);
		self
	}
}

View on GitHub (pinned to 8ebf930f17)