jdx/mise · error · eyre::Report

cache agent returned an unexpected blob lookup response

Error message

cache agent returned an unexpected blob lookup response

What it means

The blob lookup returned a response variant that does not correspond to FindBlobs at all — e.g. Stored, ActionPrediction, or Hello (src/cache/rustc.rs:508). Responses travel as JSON lines matched positionally on one stream, so a variant mismatch means request/response skew: a version-skewed agent, a desynchronized stream, or a non-mise process answering on MISE_CACHE_SOCKET. This is a wiring error, not corrupted cache data.

Source

Thrown at src/cache/rustc.rs:508

    match response {
        AgentResponse::Blobs { paths } if paths.len() == digests.len() => paths
            .into_iter()
            .zip(digests)
            .map(|(path, digest)| match path {
                Some(path) => Ok(path),
                None => bail!("cached rustc action is missing blob {}", digest.hash),
            })
            .collect(),
        AgentResponse::Blobs { .. } => {
            bail!("cache agent returned an incomplete blob lookup response")
        }
        AgentResponse::Blob { path: Some(path) } if digests.len() == 1 => Ok(vec![path]),
        AgentResponse::Blob { path: None } if digests.len() == 1 => {
            let digest = &digests[0];
            bail!("cached rustc action is missing blob {}", digest.hash)
        }
        AgentResponse::Error { message } => bail!(message),
        _ => bail!("cache agent returned an unexpected blob lookup response"),
    }
}

fn read_canonical_blob<T>(path: &Path, digest: &CacheDigest, description: &str) -> Result<T>
where
    T: DeserializeOwned + Serialize,
{
    let bytes = read_verified_blob(path, digest, description)?;
    let value = serde_json::from_slice(&bytes)
        .wrap_err_with(|| format!("cached {description} is not valid JSON"))?;
    if canonical_json(&value)? != bytes {
        bail!("cached {description} is not canonical JSON");
    }
    Ok(value)
}

fn read_verified_blob(path: &Path, digest: &CacheDigest, description: &str) -> Result<Vec<u8>> {
    let mut bytes = Vec::new();

View on GitHub (pinned to 6f52dcdf99)

Solutions

  1. Restart the mise session/task so shim and agent share one binary and protocol revision
  2. Unset inherited MISE_CACHE_* variables before invoking mise so tasks never attach to foreign agents
  3. Verify only one mise version is installed or active for the session
  4. If a custom client is involved, align it with AGENT_PROTOCOL_VERSION and the response enum of the running mise
Defensive patterns

Strategy: validation

Validate before calling

# ensure the task is talking to the agent of the session that launched it:
test -S "$MISE_CACHE_SOCKET" || echo 'no live cache agent socket — unset MISE_CACHE_* and rerun inside a mise task'

Type guard

fn is_unexpected_lookup(r: &AgentResponse) -> bool {
    !matches!(r, AgentResponse::Blobs { .. } | AgentResponse::Blob { .. } | AgentResponse::Error { .. })
}

Prevention

When it happens

Trigger: MISE_CACHE_SOCKET inherited from a session running another mise build with a different AgentResponse enum shape; a truncated or garbled line deserializing into the wrong variant; a custom tool pretending to be the cache agent.

Common situations: Stale exported MISE_CACHE_* environment in CI images or shell profiles; mixed mise versions on one machine; sockets left behind by crashed sessions being reused.

Related errors


AI-assisted analysis of jdx/mise@6f52dcdf99 (2026-08-22). Data as JSON: /api/errors/e3283f4a72998035. Report an issue: GitHub.