sxyazi/yazi · warning · io::Error
Cache stamp does not match target
Error message
Cache stamp does not match target
What it means
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.
Source
Thrown at yazi-vfs/src/stamp.rs:77
.write(data)
.await
.map_err(|e| io::Error::new(e.kind(), format!("Cannot write cache stamp: {e}")))
}
fn encode(cha: Cha, url: Url) -> io::Result<Vec<u8>> {
let name = url.name().ok_or_else(|| io::Error::other("URL has no filename"))?;
let mut buf = Vec::with_capacity(Self::SIG_LEN + name.len());
buf.extend_from_slice(cha.hash_u128_str(&mut [0; Self::SIG_LEN]).as_bytes());
buf.extend_from_slice(name.encoded_bytes());
Ok(buf)
}
pub fn validate(&self, cha: Cha, url: Url) -> io::Result<()> {
let name = url.name().ok_or_else(|| io::Error::other("URL has no filename"))?;
if self.name() != name.encoded_bytes() {
return Err(io::Error::new(io::ErrorKind::InvalidData, "Cache stamp does not match target"));
}
if self.sig() != cha.hash_u128_str(&mut [0; Self::SIG_LEN]) {
return Err(io::Error::new(
io::ErrorKind::InvalidData,
"Remote file has changed since last download",
));
}
Ok(())
}
#[inline]
pub fn sig(&self) -> &str { unsafe { str::from_utf8_unchecked(&self.0[..Self::SIG_LEN]) } }
#[inline]
pub fn name(&self) -> &[u8] { &self.0[Self::SIG_LEN..] }
}
View on GitHub (pinned to 94abcfa92f)
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
Example fix
// before
stamp.validate(cha, url.as_url())?; // InvalidData bubbles up and kills the peek
// after
match stamp.validate(cha, url.as_url()) {
Ok(()) => use_cached(url).await,
Err(e) if e.kind() == io::ErrorKind::InvalidData => refetch(url).await, // stale stamp => cache miss
Err(e) => return Err(e),
} Defensive patterns
Strategy: fallback
Validate before calling
// cheap pre-check mirroring validate()'s name comparison (SIG_LEN = 26 bytes)
if let Some(name) = url.as_url().name() {
if stamp.name() != name.encoded_bytes() {
// skip validate(); go straight to the re-download path
}
} Try / catch
match stamp.validate(cha, url.as_url()) {
Ok(()) => use_cached(url).await,
Err(e) if e.kind() == io::ErrorKind::InvalidData => refetch(url).await, // mismatch => cache miss
Err(e) => return Err(e),
} Prevention
- 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
When it happens
Trigger: 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.
Common situations: 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.
Related errors
- Remote file has changed since last download
- Invalid cache stamp
- invalid trash info path
- invalid original trash path
- invalid trash info header
AI-assisted analysis of sxyazi/yazi@94abcfa92f (2026-08-16).
Data as JSON: /api/errors/80903ebffb7ccc8e.
Report an issue: GitHub.