sxyazi/yazi · error · io::Error

Cache stamp does not match entry

Error message

Cache stamp does not match entry

What it means

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.

Source

Thrown at yazi-vfs/src/stamp.rs:48

	pub async fn resolve<U, S>(dir: U, key: S) -> io::Result<UrlBuf>
	where
		U: AsUrl,
		S: AsStrand,
	{
		let dir = dir.as_url();
		let key = key.as_strand();

		let mut path =
			dir.auth().stamp_root().ok_or_else(|| io::Error::other("Cannot determine stamp root"))?;
		path.push(key.as_os()?);

		let stamp = Self::read_at(&path).await?;
		let name = StrandCow::with(dir.loc().kind(), stamp.name()).map_err(io::Error::other)?;

		let url = dir.try_join(name)?;
		if url.hash_u128_str(&mut [0; Self::SIG_LEN]).as_bytes() != key.encoded_bytes() {
			return Err(io::Error::new(io::ErrorKind::InvalidData, "Cache stamp does not match entry"));
		}

		Ok(url)
	}

	pub async fn write(cha: Cha, url: Url<'_>) -> io::Result<()> {
		let path = url.stamp_entry().ok_or_else(|| io::Error::other("Cannot determine cache stamp"))?;
		let data = Self::encode(cha, url)?;

		Local::regular(&path)
			.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"))?;

View on GitHub (pinned to 8ebf930f17)

Solutions

  1. Treat as a cache miss: delete the mismatched stamp and re-fetch/re-write via Stamp::write with the correct entry
  2. Ensure resolve is called with the same dir and key pair used when the stamp was written
  3. Clear the cache directory if entries were created by a different Yazi version

Example fix

// before
let url = Stamp::resolve(dir, key).await?;
// after
let url = Stamp::resolve(dir, key).await
    .or_else(|e| if e.kind() == io::ErrorKind::InvalidData { cache_miss(dir, key) } else { Err(e) })
    .await?;
Defensive patterns

Strategy: validation

Validate before calling

// verify the stamp belongs to this key before trusting it
let url = dir.try_join(name)?;
let mut sig = [0u8; 16];
if url.hash_u128_str(&mut sig).as_bytes() != key.encoded_bytes() {
    // mismatch: treat as cache miss
}

Type guard

fn stamp_matches_key(stamp: &Stamp, key: &CacheKey) -> bool {
    stamp.0.len() > Stamp::SIG_LEN && !stamp.name().is_empty()
}

Try / catch

match Stamp::resolve(dir, key).await {
    Ok(url) => url,
    Err(e) if e.kind() == io::ErrorKind::InvalidData => cache_miss_fallback(),
    Err(e) => return Err(e),
}

Prevention

When it happens

Trigger: 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).

Common situations: 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.

Related errors


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