{"record":{"id":"80903ebffb7ccc8e","repo":"sxyazi/yazi","slug":"cache-stamp-does-not-match-target","errorCode":null,"errorMessage":"Cache stamp does not match target","messagePattern":"Cache stamp does not match target","errorType":"exception","errorClass":"io::Error","httpStatus":null,"severity":"warning","filePath":"yazi-vfs/src/stamp.rs","lineNumber":77,"sourceCode":"\t\t\t.write(data)\n\t\t\t.await\n\t\t\t.map_err(|e| io::Error::new(e.kind(), format!(\"Cannot write cache stamp: {e}\")))\n\t}\n\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","sourceCodeStart":59,"sourceCodeEnd":95,"githubUrl":"https://github.com/sxyazi/yazi/blob/94abcfa92f4ad3f0a1aef6c1ea083cfb8aa6c8c2/yazi-vfs/src/stamp.rs#L59-L95","documentation":"Returned by Stamp::validate with ErrorKind::InvalidData when the filename stored inside the stamp does not equal the encoded name of the URL being validated. Stamp files are keyed by a u128 hash of the URL, and the payload repeats the target filename; a mismatch means the stamp found at that key belongs to a different target, so the cached data cannot be trusted for this URL.","triggerScenarios":"Calling stamp.validate(cha, url) where stamp was read from url.stamp_entry() but stamp.name() != url.name().encoded_bytes(): a hash collision in the %stamp directory, a stamp left over after the remote file was renamed/moved, a stamp written by a different yazi version whose URL hashing differed, or temp-dir files copied around by hand.","commonSituations":"Upgrading yazi across versions that changed URL hashing while old stamp files remain in <tmp>/yazi-<uid>/.../%stamp; leftover stamps after renames on the remote side; manually restoring or copying yazi temp directories between machines.","solutions":["Treat this InvalidData as a cache miss: delete the cached entry plus its stamp and re-download the file","Clear the yazi temp stamp tree (<tmp>/yazi-<uid>/*/%stamp) after upgrading yazi so stale formats disappear","Check you are validating the exact URL the stamp was read from (same auth, scheme, domain); validating against a renamed variant always fails","If it reproduces on fresh URLs with no upgrade involved, collect the URL and stamp bytes and report a hashing-collision bug upstream"],"exampleFix":"// before\nstamp.validate(cha, url.as_url())?; // InvalidData bubbles up and kills the peek\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, // stale stamp => cache miss\n    Err(e) => return Err(e),\n}","handlingStrategy":"fallback","validationCode":"// cheap pre-check mirroring validate()'s name comparison (SIG_LEN = 26 bytes)\nif let Some(name) = url.as_url().name() {\n    if stamp.name() != name.encoded_bytes() {\n        // skip validate(); go straight to the re-download path\n    }\n}","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, // mismatch => cache miss\n    Err(e) => return Err(e),\n}","preventionTips":["Purge <tmp>/yazi-<uid> when switching yazi versions to discard stale stamp formats","Always read the stamp with Stamp::read(url) and validate against the same url, never a renamed variant","Handle ErrorKind::InvalidData from validate() as 'cache miss', never as a hard failure"],"tags":["cache","invalidation","invalid-data","sftp"],"backgroundTag":null,"analyzedSha":"94abcfa92f4ad3f0a1aef6c1ea083cfb8aa6c8c2","analyzedAt":"2026-08-16T09:56:24.836Z","schemaVersion":2},"datasetVersion":"2026-08-16T13:17:31.715Z"}