jdx/mise · error
remote cache blob pack returned an unrequested digest
Error message
remote cache blob pack returned an unrequested digest
What it means
Thrown while decoding a blob pack streamed from the remote build cache. For every entry, mise-cache-core reads the framing header (one algorithm byte, a 32-byte hash, an 8-byte big-endian size), rebuilds a CacheDigest, and requires it to be one of the digests that were POSTed in the DigestList request body. If the server includes a blob that was never requested, decoding aborts immediately so unrequested content never reaches the local content-addressed store. This is a server-contract violation: the blob pack endpoint may only return blobs from the request list.
Source
Thrown at crates/mise-cache-core/src/lib.rs:930
let (algorithm, mut hasher) = match algorithm[0] {
1 => (
"blake3",
BlobPackHasher::Blake3(Box::new(blake3::Hasher::new())),
),
2 => ("sha256", BlobPackHasher::Sha256(sha2::Sha256::new())),
_ => bail!("remote cache blob pack has an invalid digest algorithm"),
};
let mut hash = [0_u8; 32];
reader.read_exact(&mut hash).await?;
let mut size = [0_u8; 8];
reader.read_exact(&mut size).await?;
let digest = CacheDigest {
algorithm: algorithm.into(),
hash: hex::encode(hash),
size: u64::from_be_bytes(size),
};
if !requested.contains(&digest) {
bail!("remote cache blob pack returned an unrequested digest");
}
if !seen.insert(digest.clone()) {
bail!("remote cache blob pack returned a duplicate digest");
}
framed_bytes = framed_bytes
.checked_add(BLOB_PACK_HEADER_BYTES)
.and_then(|bytes| bytes.checked_add(digest.size))
.ok_or_else(|| eyre!("remote cache blob pack is too large"))?;
payload_bytes = payload_bytes
.checked_add(digest.size)
.ok_or_else(|| eyre!("remote cache blob pack payload is too large"))?;
let path = directory.path().join(blobs.len().to_string());
let mut output = tokio::fs::File::create(&path).await?;
let mut remaining = digest.size;
let mut buffer = [0_u8; 64 * 1024];
while remaining > 0 {
let limit = usize::try_from(remaining.min(buffer.len() as u64)).unwrap();View on GitHub (pinned to 6f52dcdf99)
Solutions
- Verify the cache server implements the pack contract: iterate only the requested digests and frame each entry as algorithm byte + 32-byte hash + 8-byte big-endian size after the magic header.
- Disable POST-response caching on any proxy/CDN in front of the blob pack endpoint.
- Capture the request DigestList body and the response stream, then diff entry digests against the request to identify the unrequested entry.
- If the server is third-party, pin client and server to versions tested together, or make the pack endpoint return 404/405/501 so the client falls back to per-blob GETs.
- As a last resort, clear the affected cache entries so the pack is rebuilt from a known-good state.
Defensive patterns
Strategy: try-catch
Try / catch
let pack = match remote_cache.download(staging_dir).await {
Ok(pack) => pack,
Err(err) if err.to_string().contains("blob pack") => {
// server violated the pack contract; treat as a cache miss
warn!("invalid blob pack: {err}");
return recompute_locally();
}
Err(err) => return Err(err),
}; Prevention
- Validate the cache server against the pack round-trip tests in crates/mise-cache-core before enabling blob packs.
- Do not put a caching reverse proxy in front of the blob pack POST endpoint.
- Pin the cache server and mise-cache-core to versions tested together.
When it happens
Trigger: POSTing a digest list to the blob pack endpoint (the remote cache's missing-blob download after an action cache hit) and the response stream contains an entry whose (algorithm, hash, size) triple is not in that list. Typical producers: a server that assembles the pack from its own inventory instead of the request, a proxy/CDN serving a cached POST response from a different request, or a pack-format framing mismatch between client and server versions.
Common situations: Running a custom or third-party cache server that ignores the request digest list; an HTTP proxy that reuses cached POST responses; client/server version skew where entry headers are framed differently so digests get misparsed mid-stream.
Related errors
- remote cache blob pack returned a duplicate digest
- remote cache blob pack ended before a blob was complete
- remote cache blob pack failed digest verification
- invalid remote action manifest ETag
- remote cache URL must use HTTPS
AI-assisted analysis of jdx/mise@6f52dcdf99 (2026-08-22).
Data as JSON: /api/errors/43c5243a0e298c8a.
Report an issue: GitHub.