{"record":{"id":"eb3775ea10661801","repo":"rust-lang/cargo","slug":"cache-expected-4-bytes-for-index-schema-version","errorCode":null,"errorMessage":"cache expected 4 bytes for index schema version","messagePattern":"cache expected 4 bytes for index schema version","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src/sources/registry/index/cache.rs","lineNumber":175,"sourceCode":"    pub versions: Vec<(Version, &'a [u8])>,\n    /// For cache invalidation, we tracks the index file version to determine\n    /// when to regenerate the cache itself.\n    pub index_version: &'a str,\n}\n\nimpl<'a> SummariesCache<'a> {\n    /// Deserializes an on-disk cache.\n    pub fn parse(data: &'a [u8]) -> CargoResult<SummariesCache<'a>> {\n        // NB: keep this method in sync with `serialize` below\n        let (first_byte, rest) = data\n            .split_first()\n            .ok_or_else(|| anyhow::format_err!(\"malformed cache\"))?;\n        if *first_byte != CURRENT_CACHE_VERSION {\n            bail!(\"looks like a different Cargo's cache, bailing out\");\n        }\n        let index_v_bytes = rest\n            .get(..4)\n            .ok_or_else(|| anyhow::anyhow!(\"cache expected 4 bytes for index schema version\"))?;\n        let index_v = u32::from_le_bytes(index_v_bytes.try_into().unwrap());\n        if index_v != INDEX_V_MAX {\n            bail!(\n                \"index schema version {index_v} doesn't match the version I know ({INDEX_V_MAX})\",\n            );\n        }\n        let rest = &rest[4..];\n\n        let mut iter = split(rest, 0);\n        let last_index_update = if let Some(update) = iter.next() {\n            str::from_utf8(update)?\n        } else {\n            bail!(\"malformed file\");\n        };\n        let mut ret = SummariesCache::default();\n        ret.index_version = last_index_update;\n        while let Some(version) = iter.next() {\n            let version = str::from_utf8(version)?;","sourceCodeStart":157,"sourceCodeEnd":193,"githubUrl":"https://github.com/rust-lang/cargo/blob/eb98b54bc9f3c74519f43d066cb3fd02ebc88df0/src/sources/registry/index/cache.rs#L157-L193","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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)."],"exampleFix":"# before: corrupt truncated cache\n$ cargo build\nerror: cache expected 4 bytes for index schema version\n\n# after: clear and rebuild\n$ rm -rf ~/.cargo/registry/index/*/.cache\n$ cargo fetch && cargo build","handlingStrategy":"try-catch","validationCode":"fn cache_is_parseable(data: &[u8]) -> Result<(), anyhow::Error> {\n    if data.len() < 5 { anyhow::bail!(\"cache too short ({})\", data.len()); }\n    Ok(())\n}","typeGuard":"fn cache_long_enough(data: &[u8]) -> bool { data.len() >= 5 }","tryCatchPattern":"match SummariesCache::parse(data) {\n    Ok(c) => Ok(c),\n    Err(e) if e.to_string().contains(\"expected 4 bytes\") => {\n        let _ = std::fs::remove_file(&cache_file); // recover by invalidating\n        recompute_cache()\n    }\n    Err(e) => Err(e),\n}","preventionTips":["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."],"tags":["cargo","registry","cache","corruption","deserialization"],"backgroundTag":null,"analyzedSha":"eb98b54bc9f3c74519f43d066cb3fd02ebc88df0","analyzedAt":"2026-08-11T17:42:36.556Z","contentChangedAt":"2026-08-11T17:42:36.556Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}