sxyazi/yazi · error · io::Error

Cache stamp does not match target

Error message

Cache stamp does not match target

What it means

Returned by Stamp::validate when the stamp's recorded filename differs from the target URL's name. It is an InvalidData error indicating the cached stamp belongs to a different file than the URL being validated, so the cache entry must not be trusted.

Solutions

  1. Rewrite the stamp for the current URL via Stamp::write to resynchronize name and signature
  2. Verify the stamp file being validated is the one derived from this URL (stamp_entry)
  3. If the remote renamed the file, refresh the cache entry under the new name

Example fix

// before
stamp.validate(cha, url)?;
// after
if let Err(e) = stamp.validate(cha, url) {
    if e.kind() == io::ErrorKind::InvalidData { Stamp::write(cha, url.clone()).await?; }
    else { return Err(e); }
}
Defensive patterns

Strategy: validation

Validate before calling

if let Some(name) = url.name() {
    // name must equal the stamp's recorded name before validating
    if stamp.name() != name.encoded_bytes() { /* regenerate stamp */ }
}

Type guard

fn stamp_targets(stamp: &Stamp, url: &Url) -> bool {
    url.name().map(|n| stamp.name() == n.encoded_bytes()).unwrap_or(false)
}

Try / catch

match stamp.validate(cha, url.clone()) {
    Ok(()) => (),
    Err(e) if e.kind() == io::ErrorKind::InvalidData => Stamp::write(cha, url).await?,
    Err(e) => return Err(e),
}

Prevention

When it happens

Trigger: Calling stamp.validate(cha, url) where url.name() is None would already error earlier; the specific 'does not match target' fires when self.name() != name.encoded_bytes() — i.e., the stamp was written for a differently-named file than the URL supplied.

Common situations: Reusing a cached stamp across renamed files; mixing up cache entries after a remote rename; a bug where the wrong stamp file is looked up for a URL.

Related errors


AI-assisted analysis of sxyazi/yazi@8ebf930f17 (2026-09-02). Data as JSON: /api/errors/80903ebffb7ccc8e. Report an issue: GitHub.

Appendix: 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]
	fn name(&self) -> &[u8] { &self.0[Self::SIG_LEN..] }
}

View on GitHub (pinned to 8ebf930f17)