{"record":{"id":"fe2d281621372144","repo":"jdx/mise","slug":"cache-agent-returned-an-incomplete-blob-lookup-res","errorCode":null,"errorMessage":"cache agent returned an incomplete blob lookup response","messagePattern":"cache agent returned an incomplete blob lookup response","errorType":"exception","errorClass":"eyre::Report","httpStatus":null,"severity":"error","filePath":"src/cache/rustc.rs","lineNumber":500,"sourceCode":"\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,\n{\n    let bytes = read_verified_blob(path, digest, description)?;\n    let value = serde_json::from_slice(&bytes)\n        .wrap_err_with(|| format!(\"cached {description} is not valid JSON\"))?;","sourceCodeStart":482,"sourceCodeEnd":518,"githubUrl":"https://github.com/jdx/mise/blob/6f52dcdf99e282ef7a7db68c81301fa4618d0f79/src/cache/rustc.rs#L482-L518","documentation":"A FindBlobs request was answered with AgentResponse::Blobs whose paths vector length differs from the number of digests requested (src/cache/rustc.rs:499-501). The protocol requires exactly one path slot per digest, so this is a response-shape violation by the agent, not a cache-state problem. It points at protocol/version skew between the shim and the agent process behind MISE_CACHE_SOCKET.","triggerScenarios":"session::request_agent returns Blobs with paths.len() != digests.len(): caused by a version-skewed agent process (MISE_CACHE_SOCKET pointing at a session spawned by a different mise build whose AgentResponse enum differs), a stale socket inherited from a previous session, or a deserialized/garbled response line.","commonSituations":"Exporting MISE_CACHE_SOCKET/MISE_CACHE_* in a shell profile or CI base image so tasks attach to an old agent; running two mise versions side by side where one reuses the other's session directory; a hand-crafted client speaking a different protocol revision to the socket.","solutions":["Unset inherited MISE_CACHE_SOCKET, MISE_CACHE_STAGING_DIR, MISE_CACHE_TASK and MISE_CACHE_TASK_ROOT in your shell/CI profile and let mise inject them per task","Restart the mise task/session so the shim and agent come from the same mise binary (the handshake enforces agent_version == VERSION, src/cache/session.rs:821-830)","Confirm a single mise version is active inside and outside the task (mise --version in both contexts)","If it persists with matched versions, report it as a bug with both versions and the request digest count"],"exampleFix":null,"handlingStrategy":"validation","validationCode":"# in shell profiles / CI images: never inherit a previous session's agent socket\nunset MISE_CACHE_SOCKET MISE_CACHE_STAGING_DIR MISE_CACHE_TASK MISE_CACHE_TASK_ROOT MISE_CACHE_CARGO_TARGET_DIR\n# mise re-injects these per task it launches","typeGuard":"fn is_incomplete_blobs(r: &AgentResponse, n: usize) -> bool {\n    matches!(r, AgentResponse::Blobs { paths } if paths.len() != n)\n}","tryCatchPattern":null,"preventionTips":["Never export MISE_CACHE_* variables; they are per-session and valid only for the task mise launches","Keep one mise version on PATH per session so shim and agent always match","Treat any 'incomplete/unexpected ... response' warning as wiring skew — restart the session before debugging data"],"tags":["rust","cache","agent","protocol","mise"],"backgroundTag":"agent-protocol-mismatch","analyzedSha":"6f52dcdf99e282ef7a7db68c81301fa4618d0f79","analyzedAt":"2026-08-22T10:14:23.840Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T15:18:49.778Z"}