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
- Delete the corrupt cache: `rm -rf ~/.cargo/registry/index/<name>/.cache` and re-run (Cargo rebuilds it).
- Run `cargo cache --autoclean` to prune inconsistent cache files.
- Ensure writes to `~/.cargo` are not interrupted (free disk space, avoid killing cargo mid-build).
- 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
- Avoid killing Cargo mid-build to prevent truncated cache writes.
- Periodically clear `~/.cargo/registry/index/*/.cache` on corruption.
- Keep adequate free disk space.
- Run matching Cargo versions across shared caches.
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
- registry said cache valid when no cache exists
- cannot publish with `open-namespaces`
- config.json not found
- failed to read path
- failed to verify the checksum of
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)