sxyazi/yazi · error · io::Error

Cannot write cache stamp

Error message

Cannot write cache stamp: {e}

What it means

This io::Error wraps a failure while writing the encoded stamp bytes to the stamp entry path via Local::regular().write(). The OS error kind is preserved and its Display embedded as 'Cannot write cache stamp: {e}'. It is raised in Stamp::write after the stamp path is determined and data encoded successfully.

Solutions

  1. Create the cache/stamp parent directory before writing (ensure it exists and is writable)
  2. Check free disk space and quotas on the cache volume
  3. Fix permissions on the cache directory; retry the write after remediation

Example fix

// before
Stamp::write(cha, url).await?;
// after
if let Some(path) = url.stamp_entry() {
    if let Some(parent) = path.parent() { tokio::fs::create_dir_all(parent).await?; }
}
Stamp::write(cha, url).await?;
Defensive patterns

Strategy: try-catch

Validate before calling

if let Some(path) = url.stamp_entry() {
    if let Some(parent) = path.parent() {
        tokio::fs::create_dir_all(parent).await?;
    }
}

Type guard

fn stamp_writable(path: &Path) -> bool {
    path.parent().map(|p| p.is_dir()).unwrap_or(false)
}

Try / catch

match Stamp::write(cha, url).await {
    Ok(()) => (),
    Err(e) if e.kind() == io::ErrorKind::StorageFull => warn_disk_full(),
    Err(e) => return Err(e),
}

Prevention

When it happens

Trigger: Calling Stamp::write(cha, url) when url.stamp_entry() yields a path whose parent directory does not exist, is not writable, or the async write fails (disk full, permissions, I/O error).

Common situations: Cache directory deleted at runtime; read-only cache mount; disk quota/full disk while caching a downloaded remote file; permission misconfiguration on XDG cache dir.

Related errors


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

Appendix: source

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

		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"))?;

		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"));
		}

View on GitHub (pinned to 8ebf930f17)