{"record":{"id":"0dbbb27f359308bc","repo":"sxyazi/yazi","slug":"not-a-custom-vfs-url-url","errorCode":null,"errorMessage":"Not a custom VFS URL: {url:?}","messagePattern":"Not a custom VFS URL: (.+?)","errorType":"validation","errorClass":"io::Error","httpStatus":null,"severity":"error","filePath":"yazi-vfs/src/engine/lua/lua.rs","lineNumber":112,"sourceCode":"\tasync fn hard_link<P>(&self, to: P) -> io::Result<()>\n\twhere\n\t\tP: DynPath,\n\t{\n\t\tlet from = self.url.to_owned();\n\t\tlet to = to.dyn_path().to_owned();\n\n\t\tOk(self.call(ProvideJob::HardLink { from, to }).await?.ok()?)\n\t}\n\n\tasync fn metadata(&self) -> io::Result<Cha> {\n\t\tlet url = self.url.to_owned();\n\n\t\tOk(self.call(ProvideJob::Metadata { url }).await?.0?)\n\t}\n\n\tasync fn new<'b>(url: Url<'b>) -> io::Result<Self::Me<'b>> {\n\t\tlet (Url::Mount { auth, .. } | Url::Hub { auth, .. } | Url::Scope { auth, .. }) = url else {\n\t\t\treturn Err(io::Error::new(\n\t\t\t\tio::ErrorKind::InvalidInput,\n\t\t\t\tformat!(\"Not a custom VFS URL: {url:?}\"),\n\t\t\t));\n\t\t};\n\n\t\tlet service = Vfs::service::<&ServiceLua>(auth)?;\n\t\tOk(Self::Me { url, service })\n\t}\n\n\tasync fn read_dir(self) -> io::Result<Self::ReadDir> {\n\t\tlet url = self.url.to_owned();\n\t\tlet entries: Vec<DirEntry> = self.call(ProvideJob::ReadDir { url }).await?.0?;\n\n\t\tOk(ReadDir { entries: entries.into_iter() })\n\t}\n\n\tasync fn read_link(&self) -> io::Result<PathBufDyn> {\n\t\tlet url = self.url.to_owned();","sourceCodeStart":94,"sourceCodeEnd":130,"githubUrl":"https://github.com/sxyazi/yazi/blob/5f901b886b14de1f17460b6e52e9de5d67f8aba9/yazi-vfs/src/engine/lua/lua.rs#L94-L130","documentation":"This error comes from the Lua VFS engine's mount constructor: it pattern-matches the incoming URL against the custom-VFS variants (Mount, Hub, Scope) and rejects anything else with InvalidInput. It means the URL was handed to the Lua VFS engine but does not actually belong to a Lua-backed custom filesystem. The developer likely registered or routed the URL incorrectly.","triggerScenarios":"Calling `Vfs::new(url)` / engine entry points for the Lua backend with a plain local, Sftp, Archive, Search, or regular-file URL instead of a Url::Mount/Hub/Scope carrying custom-VFS auth.","commonSituations":"A plugin forgetting to wrap paths in the proper custom VFS URL, a previewer/fetcher resolving to an unmounted custom-fs location, or a regression in URL construction after a Yazi version that changed URL variants.","solutions":["Ensure the file was entered through the plugin's mount/entry API so the URL is a Mount/Hub/Scope variant","Verify the custom filesystem is actually mounted before resolving files into it","Check code that constructs URLs manually and use the VFS factory/registry instead of raw Url construction","Inspect the URL kind (log `url:kind()`) before passing it to the Lua VFS engine"],"exampleFix":"// before\nlet file = vfs::File::new(Url::from regular path)?;\n// after\nlet url = my_plugin.mounted_url(path)?; // returns Url::Mount { .. }\nlet file = vfs::File::new(url)?;","handlingStrategy":"type-guard","validationCode":"local kind = url:kind()\nassert(kind == 'mount' or kind == 'hub' or kind == 'scope', 'URL is not a custom VFS URL: '..tostring(kind))","typeGuard":"fn is_custom_vfs_url(url: &Url) -> bool {\n    matches!(url, Url::Mount { .. } | Url::Hub { .. } | Url::Scope { .. })\n}","tryCatchPattern":"match LuaVfs::new(url).await {\n    Ok(f) => f,\n    Err(e) if e.kind() == io::ErrorKind::InvalidInput && e.to_string().contains(\"Not a custom VFS URL\") => {\n        // route to the correct engine instead\n        return generic_engine::open(url).await;\n    }\n    Err(e) => return Err(e),\n}","preventionTips":["Only construct file handles through the VFS dispatcher so URL kind selects the engine","Ensure custom filesystems are mounted before resolving their paths into file handles","Log url kind at debug boundaries when plumbing URLs between plugins and the core","After upgrades, audit manual Url constructions against the current variant set"],"tags":["vfs","url","lua","invalid-input"],"backgroundTag":"invalid-url-variant","analyzedSha":"5f901b886b14de1f17460b6e52e9de5d67f8aba9","analyzedAt":"2026-09-02T18:38:25.566Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}