jdx/mise · error
cached OCI layer diff ID mismatch
Error message
cached OCI layer diff ID mismatch
What it means
After decompressing a cached OCI layer (read_cached_layer, src/oci/layer/cache.rs:143), mise hashes the uncompressed content and compares it to the recorded diff_id (the digest of the uncompressed tar). This error means the gunzipped layer content does not match the cached `diff_id` — the compressed blob may be valid gzip but not the layer originally recorded, or the cache record is stale/wrong.
Solutions
- Invalidate the OCI layer cache (delete the cache dir or the specific layer + record) and re-run so the layer is re-fetched with fresh metadata.
- Rebuild the tool layer from source instead of using the cache if the layer was produced locally.
- Update mise — earlier versions could write inconsistent digest/diff_id records; the current code validates both on read.
- Check that the source OCI layout/registry the cache came from is not serving mutated layers under the same digest.
Example fix
# before: diff ID mismatch during cached build rm -rf ~/.cache/mise/oci # after mise build-push ... # re-extracts layer and recomputes diff_id
Defensive patterns
Strategy: fallback
Validate before calling
// after decompressing, verify before use
let diff_id = format!("sha256:{}", hex_encode(Sha256::digest(&uncompressed)));
if diff_id != record.diff_id {
eprintln!("cached diff_id stale; rebuilding layer");
rebuild_layer(image_dir)?;
} Try / catch
match read_cached_layer(...) {
Err(e) if e.to_string().contains("diff ID mismatch") => {
invalidate_cache_entry(record.digest);
rebuild_or_refetch_layer(image_dir)
}
other => other,
} Prevention
- Keep mise updated so cache records are written consistently
- Clear the OCI cache after upgrading tools/images upstream
- Rebuild layers locally after registry image mutations rather than trusting stale cache
When it happens
Trigger: Calling read_cached_layer (via build_cached_tool_layer) where the gzipped blob passes digest validation but SHA-256 of its decompressed stream != record.diff_id. Causes: cache metadata written for a different layer version, corruption inside the gzip stream that still decompresses, or a registry/layout mismatch between digest and diff_id at cache-write time.
Common situations: Cache entries created by an older mise version with a differing layer build; tool image rebuilt upstream with the same tag so the cached diff_id no longer matches; corrupted multi-stream gzip; race between cache write and read.
Understand the failure class
Background: Checksum mismatch errors: "checksum verification failed", "digest mismatch", "expected vs actual checksum" — what they mean and how to fix them — this error's family across 41 libraries.
Related errors
- cached OCI layer digest mismatch
- cached OCI layer size mismatch
- base image has layers in its manifest but diff_ids in its…
- base image has layers in its manifest but diff_ids in its…
- blob digest mismatch: got
AI-assisted analysis of jdx/mise@533346cc37 (2026-09-17).
Data as JSON: /api/errors/9528114518917970.
Report an issue: GitHub.
Appendix: source
Thrown at src/oci/layer/cache.rs:143
let bytes = std::fs::read(cache_dir.join(record.digest.trim_start_matches("sha256:")))?;
eyre::ensure!(
bytes.len() as u64 == record.size,
"cached OCI layer size mismatch"
);
let digest = format!("sha256:{}", hex_encode(&Sha256::digest(&bytes)));
eyre::ensure!(digest == record.digest, "cached OCI layer digest mismatch");
let mut decoder = flate2::read::GzDecoder::new(bytes.as_slice());
let mut hash = Sha256::new();
let mut buffer = [0; 64 * 1024];
loop {
let n = decoder.read(&mut buffer)?;
if n == 0 {
break;
}
hash.update(&buffer[..n]);
}
let diff_id = format!("sha256:{}", hex_encode(&hash.finalize()));
eyre::ensure!(
diff_id == record.diff_id,
"cached OCI layer diff ID mismatch"
);
Ok(Some(LayerBlob {
digest,
diff_id,
size: record.size,
bytes,
}))
}
fn write_cached_layer(record_path: &Path, cache_dir: &Path, blob: &LayerBlob) -> Result<()> {
crate::file::create_dir_all(cache_dir)?;
let blob_path = cache_dir.join(blob.digest.trim_start_matches("sha256:"));
// Atomic blob publication followed by atomic metadata publication lets
// concurrent builds share this cache without sharing an image index.
crate::file::write_atomic(blob_path, &blob.bytes)?;
crate::file::write_atomic(View on GitHub (pinned to 533346cc37)