jdx/mise · error · eyre::Report

base image {ref_} has {} layers in its manifest but {} diff_

Error message

base image {ref_} has {} layers in its manifest but {} diff_ids in its config — refusing to emit an OCI-spec-violating image

What it means

When `mise oci build` uses a base image (--from), it pulls the base's manifest and config and cross-checks that the number of layers in the manifest equals the number of entries in rootfs.diff_ids in the config — a requirement of the OCI image spec. A mismatch means the base image itself is malformed; mise refuses to emit a derived image whose layer chain would violate the spec, rather than producing an unloadable/unrunnable artifact.

Source

Thrown at src/oci/builder.rs:254

                .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 reuse_index = self
            .opts

View on GitHub (pinned to 9dcfcaa0dc)

Solutions

  1. Pull the base by immutable digest instead of a mutable tag to avoid concurrent-repush skew
  2. Rebuild and re-push the base image with a spec-compliant tool (docker buildx) so manifest and config agree
  3. Try a different tag or a well-known official base image to confirm the base is the problem
  4. Verify externally: `docker manifest inspect <ref>` and compare layer count with the config's rootfs.diff_ids

Example fix

# before
$ mise oci build --from myregistry.internal/base:latest ...

# after (pin digest)
$ mise oci build --from myregistry.internal/base@sha256:<digest> ...
Defensive patterns

Strategy: fallback

Validate before calling

docker manifest inspect <base-ref> 2>/dev/null | python3 -c "import json,sys; m=json.load(sys.stdin); print('layers:', len(m.get('layers',[])))"  # compare against config rootfs.diff_ids count before building

Try / catch

Catch this error during `oci build --from`; fall back to a pinned digest or an alternative well-formed base tag, and report the offending ref — do not retry the same malformed base.

Prevention

When it happens

Trigger: Building on a base image pushed by a buggy or non-conformant builder, or a registry/manifest service returning mismatched manifest and config for a tag (sometimes caused by concurrent re-pushes of the same tag, or multi-platform manifest-list skew where the wrong config is fetched for the selected platform).

Common situations: Base images from minimal/exotic build systems (hand-rolled OCI writers); a registry tag being re-pushed mid-pull; platform mismatches when pulling an arch-specific base; cache proxies serving stale configs.

Related errors


AI-assisted analysis of jdx/mise@9dcfcaa0dc (2026-08-17). Data as JSON: /api/errors/e7fe5d178501c400. Report an issue: GitHub.