{"record":{"id":"c1df7dc706448b79","repo":"sxyazi/yazi","slug":"cache-stamp-does-not-match-entry","errorCode":null,"errorMessage":"Cache stamp does not match entry","messagePattern":"Cache stamp does not match entry","errorType":"validation","errorClass":"io::Error","httpStatus":null,"severity":"error","filePath":"yazi-vfs/src/stamp.rs","lineNumber":48,"sourceCode":"\n\tpub async fn resolve<U, S>(dir: U, key: S) -> io::Result<UrlBuf>\n\twhere\n\t\tU: AsUrl,\n\t\tS: AsStrand,\n\t{\n\t\tlet dir = dir.as_url();\n\t\tlet key = key.as_strand();\n\n\t\tlet mut path =\n\t\t\tdir.auth().stamp_root().ok_or_else(|| io::Error::other(\"Cannot determine stamp root\"))?;\n\t\tpath.push(key.as_os()?);\n\n\t\tlet stamp = Self::read_at(&path).await?;\n\t\tlet name = StrandCow::with(dir.loc().kind(), stamp.name()).map_err(io::Error::other)?;\n\n\t\tlet url = dir.try_join(name)?;\n\t\tif url.hash_u128_str(&mut [0; Self::SIG_LEN]).as_bytes() != key.encoded_bytes() {\n\t\t\treturn Err(io::Error::new(io::ErrorKind::InvalidData, \"Cache stamp does not match entry\"));\n\t\t}\n\n\t\tOk(url)\n\t}\n\n\tpub async fn write(cha: Cha, url: Url<'_>) -> io::Result<()> {\n\t\tlet path = url.stamp_entry().ok_or_else(|| io::Error::other(\"Cannot determine cache stamp\"))?;\n\t\tlet data = Self::encode(cha, url)?;\n\n\t\tLocal::regular(&path)\n\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","sourceCodeStart":30,"sourceCodeEnd":66,"githubUrl":"https://github.com/sxyazi/yazi/blob/8ebf930f1796ae2076b7d6b0c5e93a1002c18134/yazi-vfs/src/stamp.rs#L30-L66","documentation":"Returned by Stamp::resolve when the stamp file at dir/key decodes fine, but re-hashing the resolved URL (hash_u128_str) does not equal the encoded key. The stamp therefore points at an entry that does not match the requested cache key — the cache lookup is inconsistent or stale.","triggerScenarios":"Calling Stamp::resolve(dir, key) where the stamp's recorded name joins to a URL whose u128 hash differs from key.encoded_bytes(): key collision handling, a stamp written for a different source entry, or a changed hashing input (e.g. remote metadata changed identity).","commonSituations":"Cache directory shared or reused across remotes/versions; a stamp file left behind after the source entry was renamed or replaced; hand-edited or copied cache entries.","solutions":["Treat as a cache miss: delete the mismatched stamp and re-fetch/re-write via Stamp::write with the correct entry","Ensure resolve is called with the same dir and key pair used when the stamp was written","Clear the cache directory if entries were created by a different Yazi version"],"exampleFix":"// before\nlet url = Stamp::resolve(dir, key).await?;\n// after\nlet url = Stamp::resolve(dir, key).await\n    .or_else(|e| if e.kind() == io::ErrorKind::InvalidData { cache_miss(dir, key) } else { Err(e) })\n    .await?;","handlingStrategy":"validation","validationCode":"// verify the stamp belongs to this key before trusting it\nlet url = dir.try_join(name)?;\nlet mut sig = [0u8; 16];\nif url.hash_u128_str(&mut sig).as_bytes() != key.encoded_bytes() {\n    // mismatch: treat as cache miss\n}","typeGuard":"fn stamp_matches_key(stamp: &Stamp, key: &CacheKey) -> bool {\n    stamp.0.len() > Stamp::SIG_LEN && !stamp.name().is_empty()\n}","tryCatchPattern":"match Stamp::resolve(dir, key).await {\n    Ok(url) => url,\n    Err(e) if e.kind() == io::ErrorKind::InvalidData => cache_miss_fallback(),\n    Err(e) => return Err(e),\n}","preventionTips":["Always pair resolve with the exact (dir, key) used at write time","Do not share one cache directory across different remotes or versions","Delete stale stamps when their source entry is renamed or removed"],"tags":["cache","integrity","validation","rust"],"backgroundTag":"cache-key-mismatch","analyzedSha":"8ebf930f1796ae2076b7d6b0c5e93a1002c18134","analyzedAt":"2026-09-02T18:38:25.566Z","contentChangedAt":"2026-09-02T18:38:25.566Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}