{"record":{"id":"bfa5124fd7efc51a","repo":"jdx/mise","slug":"cached-rustc-action-is-missing-blob","errorCode":null,"errorMessage":"cached rustc action is missing blob {}","messagePattern":"cached rustc action is missing blob (.+?)","errorType":"exception","errorClass":"eyre::Report","httpStatus":null,"severity":"warning","filePath":"src/cache/rustc.rs","lineNumber":496,"sourceCode":"            eprintln!(\"mise rustc cache warning: hit was not recorded: {error:#}\");\n        }\n    }\n}\n\nfn find_blobs(digests: &[CacheDigest]) -> Result<Vec<PathBuf>> {\n    let responses = session::request_agent(&[AgentRequest::FindBlobs {\n        digests: digests.to_vec(),\n    }])?;\n    let Some(response) = responses.into_iter().next() else {\n        bail!(\"cache agent did not return a blob lookup response\");\n    };\n    match response {\n        AgentResponse::Blobs { paths } if paths.len() == digests.len() => paths\n            .into_iter()\n            .zip(digests)\n            .map(|(path, digest)| match path {\n                Some(path) => Ok(path),\n                None => bail!(\"cached rustc action is missing blob {}\", digest.hash),\n            })\n            .collect(),\n        AgentResponse::Blobs { .. } => {\n            bail!(\"cache agent returned an incomplete blob lookup response\")\n        }\n        AgentResponse::Blob { path: Some(path) } if digests.len() == 1 => Ok(vec![path]),\n        AgentResponse::Blob { path: None } if digests.len() == 1 => {\n            let digest = &digests[0];\n            bail!(\"cached rustc action is missing blob {}\", digest.hash)\n        }\n        AgentResponse::Error { message } => bail!(message),\n        _ => bail!(\"cache agent returned an unexpected blob lookup response\"),\n    }\n}\n\nfn read_canonical_blob<T>(path: &Path, digest: &CacheDigest, description: &str) -> Result<T>\nwhere\n    T: DeserializeOwned + Serialize,","sourceCodeStart":478,"sourceCodeEnd":514,"githubUrl":"https://github.com/jdx/mise/blob/6f52dcdf99e282ef7a7db68c81301fa4618d0f79/src/cache/rustc.rs#L478-L514","documentation":"Thrown by find_blobs() while restoring a cached rustc action: the session cache agent answered a multi-digest FindBlobs request with a Blobs response whose per-digest path list contains a None slot (src/cache/rustc.rs:491-497). The content-addressed store still has the action manifest but no longer holds one of the blobs it references (named by its blake3 hash), so the cached compilation cannot be materialized. This is effectively a cache miss: compile() logs 'mise rustc cache warning: result was not restored' and runs real rustc (src/cache/rustc.rs:62-64).","triggerScenarios":"restore_result() looks up the [action descriptor, metadata, output-root] digests (src/cache/rustc.rs:301-305) or the [stdout, stderr, output-file] digests (src/cache/rustc.rs:331-333) and at least one blob was evicted from the local CAS or never downloaded from the remote cache; e.g. the cache directory was partially pruned, or a remote cache served the action manifest but its blob pack was expired or failed to download.","commonSituations":"Manual cleanup that deleted CAS object files but left action manifests; a remote cache in read mode with server-side LRU eviction; concurrent cache GC or two sessions sharing one cache dir; a disk-full condition during an earlier StoreBlob leaving manifest-without-blob entries.","solutions":["Rerun the task: the shim treats this as a miss, recompiles with real rustc, and republishes the missing blobs","If it recurs for the same action, delete the stale local action-cache directory wholesale so manifests without blobs are purged","When task.cache.remote_url is set, check remote health (token, namespace, connectivity) since failed blob-pack fetches surface as missing blobs","Ensure only one mise version uses a given cache dir and that MISE_CACHE_* variables come from the current mise session, not a stale exported environment"],"exampleFix":null,"handlingStrategy":"fallback","validationCode":"fn has_all_blobs(digests: &[CacheDigest]) -> bool {\n    matches!(\n        session::request_agent(&[AgentRequest::FindBlobs { digests: digests.to_vec() }]).as_deref(),\n        Ok([AgentResponse::Blobs { paths }])\n            if paths.len() == digests.len() && paths.iter().all(Option::is_some)\n    )\n}\n// call before restore_result() and skip the cached path when false","typeGuard":null,"tryCatchPattern":"Keep restore optional, never fatal — the shim already does `match restore_result(...) { Ok(Some(c)) => replay, Ok(None) => {}, Err(e) => eprintln!(\"mise rustc cache warning: result was not restored: {e:#}\") }` and falls through to executing rustc (src/cache/rustc.rs:62-64); preserve that degradation so a missing blob only costs a recompile.","preventionTips":["Never partially delete the cache directory; remove it wholesale so manifests and blobs stay consistent","Give each mise version its own cache directory when upgrading","Watch the 'Action cache: N hits, M misses' summary — rising misses paired with missing-blob warnings indicate eviction or a failing remote cache"],"tags":["rust","rustc","cache","content-addressable-storage","cache-miss"],"backgroundTag":"content-addressable-cache-missing-blob","analyzedSha":"6f52dcdf99e282ef7a7db68c81301fa4618d0f79","analyzedAt":"2026-08-22T10:14:23.840Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T15:18:49.778Z"}