{"record":{"id":"6b2da7e3536b50b8","repo":"sxyazi/yazi","slug":"not-a-local-url-url-6b2da7","errorCode":null,"errorMessage":"Not a local URL: {url:?}","messagePattern":"Not a local URL: (.+?)","errorType":"exception","errorClass":"io::Error","httpStatus":null,"severity":"error","filePath":"yazi-fs/src/engine/local/local.rs","lineNumber":91,"sourceCode":"\twhere\n\t\tP: DynPath,\n\t{\n\t\tlet to = to.dyn_path().as_os()?;\n\n\t\ttokio::fs::hard_link(self.path, to).await\n\t}\n\n\t#[inline]\n\tasync fn metadata(&self) -> io::Result<Cha> {\n\t\tOk(Cha::new(self.path.file_name().unwrap_or_default(), tokio::fs::metadata(self.path).await?))\n\t}\n\n\t#[inline]\n\tasync fn new<'b>(url: Url<'b>) -> io::Result<Self::Me<'b>> {\n\t\tmatch url {\n\t\t\tUrl::Regular(loc) | Url::Search { loc, .. } => Ok(Self::Me { url, path: loc.as_inner() }),\n\t\t\tUrl::Mount { .. } | Url::Hub { .. } | Url::Scope { .. } | Url::Sftp { .. } => {\n\t\t\t\tErr(io::Error::new(io::ErrorKind::InvalidInput, format!(\"Not a local URL: {url:?}\")))\n\t\t\t}\n\t\t}\n\t}\n\n\t#[inline]\n\tasync fn read_dir(self) -> io::Result<Self::ReadDir> {\n\t\tOk(match self.url.kind() {\n\t\t\tAuthKind::Regular => Self::ReadDir::Regular(tokio::fs::read_dir(self.path).await?),\n\t\t\tAuthKind::Search => Self::ReadDir::Others {\n\t\t\t\treader: tokio::fs::read_dir(self.path).await?,\n\t\t\t\tdir:    Arc::new(self.url.to_owned()),\n\t\t\t},\n\t\t\tAuthKind::Mount | AuthKind::Hub | AuthKind::Scope | AuthKind::Sftp => Err(io::Error::new(\n\t\t\t\tio::ErrorKind::InvalidInput,\n\t\t\t\tformat!(\"Not a local URL: {:?}\", self.url),\n\t\t\t))?,\n\t\t})\n\t}","sourceCodeStart":73,"sourceCodeEnd":109,"githubUrl":"https://github.com/sxyazi/yazi/blob/94abcfa92f4ad3f0a1aef6c1ea083cfb8aa6c8c2/yazi-fs/src/engine/local/local.rs#L73-L109","documentation":"`Local::new(url)` (yazi-fs/src/engine/local/local.rs:91) constructs a local-filesystem handle only from `Url::Regular` and `Url::Search` variants. Any other variant (`Mount`, `Hub`, `Scope`, `Sftp`) is rejected with `ErrorKind::InvalidInput` and the message `Not a local URL: {url:?}`. The constructor is the single gatekeeper that keeps non-local URLs out of the local engine.","triggerScenarios":"Calling `Local::new(url)` (or `read_dir`/metadata helpers that build a `Local` first) with a `Url` parsed from `sftp://…`, `mount://…`, a hub/scope URL, or a test URL like `test-hub://a1/@root/a`.","commonSituations":"A plugin or test iterates URLs of mixed kinds and feeds each to the local engine without filtering; a config or script embeds a remote URL string that parses into a non-`Regular` variant.","solutions":["Match on the URL before constructing: handle `Url::Regular(loc) | Url::Search { loc, .. }` with the local engine and send other kinds to their own backend.","Check `url.kind()` against `AuthKind::Regular | AuthKind::Search` as a pre-condition.","Fix the upstream URL construction so only local paths reach this code."],"exampleFix":"// before\nlet local = Local::new(url).await?; // Err for Url::Sftp\n\n// after\nmatch url {\n    Url::Regular(loc) | Url::Search { loc, .. } => { let local = Local::new(url).await?; /* ... */ }\n    _ => { /* use the engine for Mount/Hub/Scope/Sftp */ }\n}","handlingStrategy":"type-guard","validationCode":"use yazi_fs::engine::AuthKind;\n\nif !matches!(url.kind(), AuthKind::Regular | AuthKind::Search) {\n    // do not construct Local from this URL\n}","typeGuard":"fn accepts_local(url: &Url) -> bool {\n    matches!(url, Url::Regular(_) | Url::Search { .. })\n}","tryCatchPattern":"match Local::new(url).await {\n    Ok(me) => { /* ... */ }\n    Err(e) if e.kind() == io::ErrorKind::InvalidInput => { /* re-dispatch by url.kind() */ }\n    Err(e) => return Err(e),\n}","preventionTips":["Construct backend handles only through the engine registry that selects on URL kind.","Keep a single match over the Url enum as the construction gate; do not duplicate it per call site.","Treat 'Not a local URL' errors as programming bugs (wrong dispatch), not runtime noise."],"tags":["url","local-engine","constructor","input-validation"],"backgroundTag":null,"analyzedSha":"94abcfa92f4ad3f0a1aef6c1ea083cfb8aa6c8c2","analyzedAt":"2026-08-16T09:56:24.836Z","schemaVersion":2},"datasetVersion":"2026-08-16T13:17:31.715Z"}