{"record":{"id":"e7fe5d178501c400","repo":"jdx/mise","slug":"base-image-ref-has-layers-in-its-manifest-bu","errorCode":null,"errorMessage":"base image {ref_} has {} layers in its manifest but {} diff_ids in its config — refusing to emit an OCI-spec-violating image","messagePattern":"base image (.+?) has (.+?) layers in its manifest but (.+?) diff_ids in its config — refusing to emit an OCI-spec-violating image","errorType":"exception","errorClass":"eyre::Report","httpStatus":null,"severity":"error","filePath":"src/oci/builder.rs","lineNumber":254,"sourceCode":"                .get(\"rootfs\")\n                .and_then(|r| r.get(\"diff_ids\"))\n                .and_then(|d| d.as_array())\n                .ok_or_else(|| {\n                    eyre::eyre!(\n                        \"pulled base image {ref_} has no rootfs.diff_ids in its config \\\n                         — cannot produce a valid OCI image on top of it\"\n                    )\n                })?;\n            base_diff_ids = diff_ids_raw\n                .iter()\n                .map(|v| {\n                    v.as_str().map(String::from).ok_or_else(|| {\n                        eyre::eyre!(\"base image {ref_} has a non-string entry in rootfs.diff_ids\")\n                    })\n                })\n                .collect::<Result<Vec<_>>>()?;\n            if base_diff_ids.len() != base_layers.len() {\n                bail!(\n                    \"base image {ref_} has {} layers in its manifest but {} diff_ids in its \\\n                     config — refusing to emit an OCI-spec-violating image\",\n                    base_layers.len(),\n                    base_diff_ids.len()\n                );\n            }\n            platform = pull.platform;\n            base_config_json = Some(pull.config_json);\n        }\n\n        // --- 2. Decide layer reuse and validate tool installs ---\n        // A tool layer is reused from the remote cache image when tool,\n        // version, in-image prefix, and file owner all match — in that case\n        // the layer is never built locally and the tool doesn't need to be\n        // installed at all.\n        let owner_str = format!(\"{}:{}\", owner.uid, owner.gid);\n        let reuse_index = self\n            .opts","sourceCodeStart":236,"sourceCodeEnd":272,"githubUrl":"https://github.com/jdx/mise/blob/9dcfcaa0dc8747a2577d3270b69bb9d8313b2807/src/oci/builder.rs#L236-L272","documentation":"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.","triggerScenarios":"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).","commonSituations":"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.","solutions":["Pull the base by immutable digest instead of a mutable tag to avoid concurrent-repush skew","Rebuild and re-push the base image with a spec-compliant tool (docker buildx) so manifest and config agree","Try a different tag or a well-known official base image to confirm the base is the problem","Verify externally: `docker manifest inspect <ref>` and compare layer count with the config's rootfs.diff_ids"],"exampleFix":"# before\n$ mise oci build --from myregistry.internal/base:latest ...\n\n# after (pin digest)\n$ mise oci build --from myregistry.internal/base@sha256:<digest> ...","handlingStrategy":"fallback","validationCode":"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","typeGuard":null,"tryCatchPattern":"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.","preventionTips":["Pin base images by digest (@sha256:...) rather than mutable tags","Produce base images with mainstream builders (docker buildx) that keep manifest and config consistent","Include a base-image manifest/config sanity check in the pipeline that publishes your base"],"tags":["oci","base-image","manifest","spec-violation","registry"],"backgroundTag":"oci-image-manifest-invalid","analyzedSha":"9dcfcaa0dc8747a2577d3270b69bb9d8313b2807","analyzedAt":"2026-08-17T14:28:50.624Z","schemaVersion":2},"datasetVersion":"2026-08-21T18:17:14.833Z"}