jdx/mise · critical
base image {ref_} has {base_layers.len} layers in its manife
Error message
base image {ref_} has {base_layers.len} layers in its manifest but {base_diff_ids.len} diff_ids in its config — refusing to emit an OCI-spec-violating image What it means
When reusing a base image, mise cross-checks the manifest's layer list against the config's `rootfs.diff_ids` array; the OCI spec requires one diff_id per layer. If the counts diverge, the downloaded base image is malformed or mismatched (or the two documents came from different images), and mise refuses to build a spec-violating image on top of it.
Source
Thrown at src/oci/builder.rs:261
.get("rootfs")
.and_then(|r| r.get("diff_ids"))
.and_then(|d| d.as_array())
.ok_or_else(|| {
eyre::eyre!(
"pulled base image {ref_} has no rootfs.diff_ids in its config \
— cannot produce a valid OCI image on top of it"
)
})?;
base_diff_ids = diff_ids_raw
.iter()
.map(|v| {
v.as_str().map(String::from).ok_or_else(|| {
eyre::eyre!("base image {ref_} has a non-string entry in rootfs.diff_ids")
})
})
.collect::<Result<Vec<_>>>()?;
if base_diff_ids.len() != base_layers.len() {
bail!(
"base image {ref_} has {} layers in its manifest but {} diff_ids in its \
config — refusing to emit an OCI-spec-violating image",
base_layers.len(),
base_diff_ids.len()
);
}
platform = pull.platform;
base_config_json = Some(pull.config_json);
}
// --- 2. Decide layer reuse and validate tool installs ---
// A tool layer is reused from the remote cache image when tool,
// version, in-image prefix, and file owner all match — in that case
// the layer is never built locally and the tool doesn't need to be
// installed at all.
let owner_str = format!("{}:{}", owner.uid, owner.gid);
let python_relocations: Vec<PythonRelocation> = versions
.iter()View on GitHub (pinned to afd2eddd3a)
Solutions
- Re-pull the base image (clear any cache/mirror) so manifest and config come from the same digest-pinned source: `docker pull <ref>@sha256:<digest>` and pin the digest in config.
- Verify the registry/mirror isn't rewriting content; bypass the mirror and pull from the upstream registry.
- Check for tooling that edited the image config (custom `docker commit`/save-load round trips) and regenerate the base image.
- Report the mismatch to the registry operator if a specific tag consistently returns inconsistent manifest/config.
Example fix
// before (mutable tag through a flaky mirror) let base = "mirror.internal/mybase:latest"; // after (digest-pinned, consistent manifest+config) let base = "mirror.internal/mybase@sha256:abc123...";
Defensive patterns
Strategy: validation
Validate before calling
// before building, verify layer/diff_id consistency of the base image
const ok = baseManifest.layers.length === baseConfig.rootfs.diff_ids.length;
if (!ok) throw new Error('base image manifest/config layer count mismatch — re-pull'); Prevention
- Pin base images by digest (`ref@sha256:...`) so manifest and config always come from the same content.
- Avoid flaky mirrors/proxies that can serve mismatched blobs.
- Re-pull the base image if it was force-pushed or mutated.
- Validate the pulled image with a tool (e.g. `cosign`/schema checks) before using it as a base.
When it happens
Trigger: Pulling a base image whose manifest and config disagree on layer count — e.g. a corrupted/mutated registry cache, a proxy or mirror serving mismatched blobs, or fetching the manifest of one tag and the config of another.
Common situations: Corporate registry mirrors rewriting manifests; interrupted/corrupted local image caches; manually constructing or trimming image layers; registry bugs after force-pushing a tag with different content.
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
- blob digest mismatch: got {actual}, expected {digest}
- task action manifest is not canonical JSON
- remote action descriptor is missing
- remote action metadata is missing
- remote action output file is missing
AI-assisted analysis of jdx/mise@afd2eddd3a (2026-09-09).
Data as JSON: /api/errors/06458709e0ef78d0.
Report an issue: GitHub.