sxyazi/yazi · error · io::Error

Invalid cache stamp

Error message

Invalid cache stamp

What it means

Produced by TryFrom<Vec<u8>> for Stamp when the raw bytes cannot be split into a non-empty signature of SIG_LEN bytes plus a non-empty name — i.e., the buffer is too short or malformed, marked InvalidData with message 'Invalid cache stamp'.

Solutions

  1. Delete the malformed stamp file and regenerate it (re-download + Stamp::write)
  2. Purge the whole cache directory to remove all corrupt stamps
  3. Check for partial-write issues; ensure writes are atomic (write-temp-then-rename) if customizing

Example fix

// before
let stamp = Stamp::try_from(bytes)?;
// after
fn is_plausible_stamp(b: &[u8]) -> bool { b.len() > SIG_LEN }
if !is_plausible_stamp(&bytes) { std::fs::remove_file(&stamp_path)?; return cache_miss(); }
Defensive patterns

Strategy: validation

Validate before calling

let data = tokio::fs::read(&stamp_path).await?;
let ok = data.len() > Stamp::SIG_LEN && !data[Stamp::SIG_LEN..].is_empty();
if !ok { std::fs::remove_file(&stamp_path).await.ok(); /* cache miss */ }

Type guard

fn is_valid_stamp_shape(data: &[u8]) -> bool {
    data.split_at_checked(Stamp::SIG_LEN)
        .map(|(_, name)| !name.is_empty())
        .unwrap_or(false)
}

Try / catch

match Stamp::try_from(data) {
    Ok(s) => s,
    Err(e) if e.kind() == io::ErrorKind::InvalidData => { drop_corrupt_stamp(); cache_miss() },
    Err(e) => return Err(e.into()),
}

Prevention

When it happens

Trigger: Stamp::try_from(bytes) (called from read_at) with a Vec shorter than SIG_LEN, exactly SIG_LEN with no name bytes, or an empty buffer — typically a truncated or empty stamp file.

Common situations: Crash or disk-full during Stamp::write leaving a 0-byte/partial file; a different stamp binary format written by another tool or version in the cache directory.

Related errors


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

Appendix: source

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

		}
		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..] }
}

impl TryFrom<Vec<u8>> for Stamp {
	type Error = io::Error;

	fn try_from(value: Vec<u8>) -> Result<Self, Self::Error> {
		let (sig, _) = value
			.split_at_checked(Self::SIG_LEN)
			.filter(|(_, n)| !n.is_empty())
			.ok_or_else(|| io::Error::new(io::ErrorKind::InvalidData, "Invalid cache stamp"))?;

		str::from_utf8(sig).map_err(|e| io::Error::new(io::ErrorKind::InvalidData, e))?;
		Ok(Self(value))
	}
}

View on GitHub (pinned to 8ebf930f17)