rust-lang/cargo · error

cache expected 4 bytes for index schema version

Error message

cache expected 4 bytes for index schema version

What it means

Parsing the on-disk summaries cache (`SummariesCache::parse`), after consuming the version byte, Cargo reads the next 4 bytes as a little-endian `u32` schema version. If the remaining buffer is shorter than 4 bytes (`rest.get(..4)` returns `None`), the cache file is truncated/corrupt and cannot be decoded.

Solutions

  1. Delete the corrupt cache: `rm -rf ~/.cargo/registry/index/<name>/.cache` and re-run (Cargo rebuilds it).
  2. Run `cargo cache --autoclean` to prune inconsistent cache files.
  3. Ensure writes to `~/.cargo` are not interrupted (free disk space, avoid killing cargo mid-build).
  4. Upgrade Cargo to a version that handles truncated cache more gracefully (re-fetch instead of error).

Example fix

# before: corrupt truncated cache
$ cargo build
error: cache expected 4 bytes for index schema version

# after: clear and rebuild
$ rm -rf ~/.cargo/registry/index/*/.cache
$ cargo fetch && cargo build
Defensive patterns

Strategy: try-catch

Validate before calling

fn cache_is_parseable(data: &[u8]) -> Result<(), anyhow::Error> {
    if data.len() < 5 { anyhow::bail!("cache too short ({})", data.len()); }
    Ok(())
}

Type guard

fn cache_long_enough(data: &[u8]) -> bool { data.len() >= 5 }

Try / catch

match SummariesCache::parse(data) {
    Ok(c) => Ok(c),
    Err(e) if e.to_string().contains("expected 4 bytes") => {
        let _ = std::fs::remove_file(&cache_file); // recover by invalidating
        recompute_cache()
    }
    Err(e) => Err(e),
}

Prevention

When it happens

Trigger: The cache file at `~/.cargo/registry/index/<name>/.cache/<dep-path>` is shorter than 5 bytes (1 version byte + 4 schema-version bytes). Caused by an interrupted write, disk full, concurrent writer crash, or filesystem corruption.

Common situations: Cargo killed (OOM, signal, power loss) mid-write of the cache file; full disk; sync/atomic-rename failure; mismatched Cargo versions writing partial cache. Cargo will normally treat this as recoverable by re-fetching, but the parse error surfaces when it doesn't.

Related errors


AI-assisted analysis of rust-lang/cargo@eb98b54bc9 (2026-08-11). Data as JSON: /api/errors/eb3775ea10661801. Report an issue: GitHub.

Appendix: source

Thrown at src/sources/registry/index/cache.rs:175

    pub versions: Vec<(Version, &'a [u8])>,
    /// For cache invalidation, we tracks the index file version to determine
    /// when to regenerate the cache itself.
    pub index_version: &'a str,
}

impl<'a> SummariesCache<'a> {
    /// Deserializes an on-disk cache.
    pub fn parse(data: &'a [u8]) -> CargoResult<SummariesCache<'a>> {
        // NB: keep this method in sync with `serialize` below
        let (first_byte, rest) = data
            .split_first()
            .ok_or_else(|| anyhow::format_err!("malformed cache"))?;
        if *first_byte != CURRENT_CACHE_VERSION {
            bail!("looks like a different Cargo's cache, bailing out");
        }
        let index_v_bytes = rest
            .get(..4)
            .ok_or_else(|| anyhow::anyhow!("cache expected 4 bytes for index schema version"))?;
        let index_v = u32::from_le_bytes(index_v_bytes.try_into().unwrap());
        if index_v != INDEX_V_MAX {
            bail!(
                "index schema version {index_v} doesn't match the version I know ({INDEX_V_MAX})",
            );
        }
        let rest = &rest[4..];

        let mut iter = split(rest, 0);
        let last_index_update = if let Some(update) = iter.next() {
            str::from_utf8(update)?
        } else {
            bail!("malformed file");
        };
        let mut ret = SummariesCache::default();
        ret.index_version = last_index_update;
        while let Some(version) = iter.next() {
            let version = str::from_utf8(version)?;

View on GitHub (pinned to eb98b54bc9)