{"record":{"id":"512d8a0e492d1463","repo":"sxyazi/yazi","slug":"revalidated-file-url-changed","errorCode":null,"errorMessage":"revalidated file URL changed","messagePattern":"revalidated file URL changed","errorType":"validation","errorClass":"io::Error","httpStatus":null,"severity":"error","filePath":"yazi-vfs/src/entries.rs","lineNumber":65,"sourceCode":"\t\tasync fn go(entries: &[DirEntry]) -> Vec<File> {\n\t\t\tlet mut files = Vec::with_capacity(entries.len());\n\t\t\tfor dent in entries {\n\t\t\t\tfiles.push(match dent.file().await {\n\t\t\t\t\tOk(file) => file,\n\t\t\t\t\tErr(_) => File::from_dummy(dent.url(), dent.file_type().await.ok()),\n\t\t\t\t});\n\t\t\t}\n\t\t\tfiles\n\t\t}\n\n\t\tlet (first, second, third) = join!(go(first), go(second), go(third));\n\t\tOk([first, second, third].into_iter().flatten().collect())\n\t}\n\n\tasync fn revalidate(old: &File) -> io::Result<Option<File>> {\n\t\tmatch engine::revalidate(old).await? {\n\t\t\tSome(new) if new.url != old.url => {\n\t\t\t\tErr(io::Error::new(io::ErrorKind::InvalidData, \"revalidated file URL changed\"))\n\t\t\t}\n\t\t\tSome(new) if !new.is_dir() => Err(io::ErrorKind::NotADirectory.into()),\n\t\t\tSome(new) => Ok(Some(new)),\n\t\t\tNone if PARTITIONS.read().timeless(old.cha) => Ok(Some(old.clone())),\n\t\t\tNone => Ok(None),\n\t\t}\n\t}\n}\n","sourceCodeStart":47,"sourceCodeEnd":74,"githubUrl":"https://github.com/sxyazi/yazi/blob/8ebf930f1796ae2076b7d6b0c5e93a1002c18134/yazi-vfs/src/entries.rs#L47-L74","documentation":"During directory revalidation, entries are re-stat'ed and compared against the cached `File`; if the fresh entry's URL differs from the cached one, this InvalidData error is thrown. Because a file's URL should be stable across a revalidation (same key/urn in the same folder), a change signals corruption or a broken engine `revalidate` implementation rather than a normal rename (renames go through explicit events, not revalidation).","triggerScenarios":"An engine's `revalidate` returns a File whose `url` differs from the input — e.g. a backend normalizing the path differently, changing case, resolving symlinks into the URL, or returning an entry for a different file entirely.","commonSituations":"Backends that canonicalize or percent-decode the urn during stat, remote servers returning differently-escaped names, or a bug in a custom Lua VFS returning the wrong entry from its metadata/cha hook.","solutions":["Fix the engine's revalidate/metadata implementation to return an entry with the identical URL it was queried with","If the backend canonicalizes names, normalize at the adapter so the URL round-trips unchanged","Check for symlink-following or case-folding in the backend stat path and disable it for keying","Catch the error and drop the stale entry (trigger a full directory reload) instead of failing the whole revalidation"],"exampleFix":"// before (in a custom engine's revalidate)\nOk(Some(File::new(canonical_url, cha))) // url changed -> InvalidData\n// after\nOk(Some(File::new(old.url.clone(), cha))) // preserve queried URL","handlingStrategy":"try-catch","validationCode":"// Engines must return the queried URL unchanged; assert at the adapter boundary\ndebug_assert_eq!(new.url, old.url, \"engine revalidate changed the URL\");","typeGuard":null,"tryCatchPattern":"match entries::revalidate(old).await {\n    Err(e) if e.to_string() == \"revalidated file URL changed\" => {\n        // engine bug or name normalization — drop the stale entry and schedule a full reload\n        log::warn!(\"revalidate changed URL for {:?}; forcing reload\", old.url);\n        reload_partition(old.url.parent()).await\n    }\n    r => r,\n}","preventionTips":["Engine implementations must return a File whose URL equals the one queried — never canonicalize, decode, or resolve symlinks into the URL","Normalize names in the backend adapter so URLs round-trip identically","Handle renames via explicit rename events, not by letting revalidate return a different URL","On this error, fall back to a full directory refresh instead of propagating the failure"],"tags":["vfs","revalidation","invariant","invalid-data"],"backgroundTag":"revalidate-url-changed","analyzedSha":"8ebf930f1796ae2076b7d6b0c5e93a1002c18134","analyzedAt":"2026-09-02T18:38:25.566Z","contentChangedAt":"2026-09-02T18:38:25.566Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}