rust-lang/cargo · error · anyhow::Error
registry said cache valid when no cache exists
Error message
registry said cache valid when no cache exists
What it means
When loading a crate summary, Cargo first checks its on-disk cache and sends the cached `index_version` to the backend; if the backend responds `LoadResponse::CacheValid` (meaning 'your cache is current') but Cargo has no cached summary at all, it bails (src/sources/registry/index/mod.rs:552). A backend must only claim cache-validity relative to a version the client actually holds.
Source
Thrown at src/sources/registry/index/mod.rs:555
Ok((s, v)) => {
cached_summaries = Some(s);
index_version = Some(v);
}
Err(e) => {
tracing::debug!("failed to parse {lowered_name:?} cache: {e}");
}
}
}
let response = load
.load(root, relative.as_ref(), index_version.as_deref())
.await?;
match response {
LoadResponse::CacheValid => {
tracing::debug!("fast path for registry cache of {:?}", relative);
if cached_summaries.is_none() {
return Err(anyhow::anyhow!(
"registry said cache valid when no cache exists"
));
}
return Ok(cached_summaries);
}
LoadResponse::NotFound => {
cache_manager.invalidate(lowered_name);
return Ok(None);
}
LoadResponse::Data {
raw_data,
index_version,
} => {
// This is the fallback path where we actually talk to the registry backend to load
// information. Here we parse every single line in the index (as we need
// to find the versions)
tracing::debug!("slow path for {:?}", relative);
let mut cache = SummariesCache::default();View on GitHub (pinned to 0e07a15537)
Solutions
- Delete the registry cache for that crate/registry and retry: `rm -rf ~/.cargo/registry/index/<reg>/`.
- If you maintain a custom `RegistryData` impl, only return `CacheValid` when you were actually passed a non-`None` `index_version` AND you can confirm the client holds that version.
- Ensure no other process is mutating `~/.cargo/registry/` concurrently (Cargo uses file locks; external cleaners bypass them).
Defensive patterns
Strategy: validation
Validate before calling
// Custom RegistryData impls: only claim CacheValid when a cache actually exists.
async fn load(&self, root: &Path, path: &Path, index_version: Option<&str>) -> CargoResult<LoadResponse> {
if let Some(v) = index_version {
if !self.cache_exists(path)? { return Ok(LoadResponse::Data { /* ... */ }); }
if v == self.server_version(path)? { return Ok(LoadResponse::CacheValid); }
}
// ... fetch fresh
} Prevention
- Only return `LoadResponse::CacheValid` when the caller passed a non-None index_version AND a local cache is present.
- Don't delete cache files out from under a running cargo (use cargo's own cache commands).
When it happens
Trigger: A registry backend (`load` impl) returns `CacheValid` while the caller's `cached_summaries` is `None` — i.e. an inconsistency between 'do you have a cache?' and 'is it valid?'. Typically a bug in a custom `RegistryData` implementation, or a state-machine glitch where the cache file was deleted between the version check and the load.
Common situations: Custom/alternative registry backends with a buggy `load()` that returns `CacheValid` unconditionally; concurrent processes deleting the cache file mid-operation; a corrupt cache that failed to parse (so `cached_summaries` is None) yet the backend still says valid.
Related errors
- cache expected 4 bytes for index schema version
- path `{}` is not a blob in the git repo
- non UTF8 path: {}
- invalid tarball downloaded, contains a file at {entry_path:?
- invalid tarball downloaded, contains an entry at {entry_path
AI-assisted analysis of rust-lang/cargo@0e07a15537 (2026-08-06).
Data as JSON: /data/errors/fc7c558b3f71cfcf.json.
Report an issue: GitHub.