{"record":{"id":"9d5c934e8d2c72ee","repo":"sxyazi/yazi","slug":"remote-file-has-changed-since-last-download","errorCode":null,"errorMessage":"Remote file has changed since last download","messagePattern":"Remote file has changed since last download","errorType":"exception","errorClass":"io::Error","httpStatus":null,"severity":"warning","filePath":"yazi-vfs/src/stamp.rs","lineNumber":81,"sourceCode":"\n\tfn encode(cha: Cha, url: Url) -> io::Result<Vec<u8>> {\n\t\tlet name = url.name().ok_or_else(|| io::Error::other(\"URL has no filename\"))?;\n\n\t\tlet mut buf = Vec::with_capacity(Self::SIG_LEN + name.len());\n\t\tbuf.extend_from_slice(cha.hash_u128_str(&mut [0; Self::SIG_LEN]).as_bytes());\n\t\tbuf.extend_from_slice(name.encoded_bytes());\n\n\t\tOk(buf)\n\t}\n\n\tpub fn validate(&self, cha: Cha, url: Url) -> io::Result<()> {\n\t\tlet name = url.name().ok_or_else(|| io::Error::other(\"URL has no filename\"))?;\n\t\tif self.name() != name.encoded_bytes() {\n\t\t\treturn Err(io::Error::new(io::ErrorKind::InvalidData, \"Cache stamp does not match target\"));\n\t\t}\n\n\t\tif self.sig() != cha.hash_u128_str(&mut [0; Self::SIG_LEN]) {\n\t\t\treturn Err(io::Error::new(\n\t\t\t\tio::ErrorKind::InvalidData,\n\t\t\t\t\"Remote file has changed since last download\",\n\t\t\t));\n\t\t}\n\t\tOk(())\n\t}\n\n\t#[inline]\n\tpub fn sig(&self) -> &str { unsafe { str::from_utf8_unchecked(&self.0[..Self::SIG_LEN]) } }\n\n\t#[inline]\n\tpub fn name(&self) -> &[u8] { &self.0[Self::SIG_LEN..] }\n}\n\nimpl TryFrom<Vec<u8>> for Stamp {\n\ttype Error = io::Error;\n\n\tfn try_from(value: Vec<u8>) -> Result<Self, Self::Error> {","sourceCodeStart":63,"sourceCodeEnd":99,"githubUrl":"https://github.com/sxyazi/yazi/blob/94abcfa92f4ad3f0a1aef6c1ea083cfb8aa6c8c2/yazi-vfs/src/stamp.rs#L63-L99","documentation":"Returned by Stamp::validate with ErrorKind::InvalidData when the 26-byte signature (Cha hashed via hash_u128_str) stored in the stamp no longer equals the hash of the file's current metadata. This is the intended integrity signal: the remote file was modified after it was downloaded into the local cache, so the cached copy is stale.","triggerScenarios":"The remote file behind an SFTP/Hub/Mount URL is edited, replaced, or touched (changing size/mtime captured in Cha) between the download that wrote the stamp and a later validate(cha, url) call; the cached copy then corresponds to an older version of the file.","commonSituations":"Previewing a remote log or document that is still being written; another client editing the file while yazi holds a cached copy; server-side rsync/touch changing mtime without content changes.","solutions":["Invalidate the cached copy and re-download the file — this error is designed to trigger exactly that","Delete the cached entry and its stamp under the auth's cache root and %stamp root, then retry the operation","If the change is only mtime noise (for example rsync -a touching files), ignore mtime in your own comparison or re-stamp after confirming content is unchanged","In plugins and wrappers, match ErrorKind::InvalidData from validate() and trigger a fresh fetch instead of surfacing the error to the user"],"exampleFix":"// before\nstamp.validate(cha, url.as_url())?; // \"Remote file has changed since last download\" surfaces to the user\n\n// after\nmatch stamp.validate(cha, url.as_url()) {\n    Ok(()) => use_cached(url).await,\n    Err(e) if e.kind() == io::ErrorKind::InvalidData => refetch(url).await,\n    Err(e) => return Err(e),\n}","handlingStrategy":"fallback","validationCode":null,"typeGuard":null,"tryCatchPattern":"match stamp.validate(cha, url.as_url()) {\n    Ok(()) => use_cached(url).await,\n    Err(e) if e.kind() == io::ErrorKind::InvalidData => refetch(url).await, // remote changed => refresh\n    Err(e) => return Err(e),\n}","preventionTips":["Expect this error on volatile remote files; always code the re-fetch path alongside the cached path","For frequently-touched files, refresh the stamp after confirming content equality so mtime noise does not force re-downloads","Never cache write-heavy remote files without a validate-then-refetch branch"],"tags":["cache","stale-data","sftp","invalidation"],"backgroundTag":null,"analyzedSha":"94abcfa92f4ad3f0a1aef6c1ea083cfb8aa6c8c2","analyzedAt":"2026-08-16T09:56:24.836Z","schemaVersion":2},"datasetVersion":"2026-08-16T13:17:31.715Z"}