The image struct in mutate/image.go is the backing implementation for all v1.Image mutators (Annotations, MediaType, AppendLayers, etc.). Its compute() method unconditionally calls base.ConfigFile() and derives the layer set from configFile.RootFS.DiffIDs. For non-Docker OCI artifacts — Helm charts, WASM modules, arbitrary blobs — the config is not a Docker image config, so RootFS.DiffIDs is empty.
This causes two problems:
-
Layers() returns an empty slice. remote.Write uses Layers() to determine which blobs to upload. On a cross-repository push, layer blobs are never uploaded, and the registry rejects the manifest with MANIFEST_BLOB_UNKNOWN.
-
The config blob digest is corrupted. compute() re-marshals the config file and writes the new digest into the manifest, so the manifest now references a config blob whose content differs from the original. The original config blob is never uploaded.
Any mutator that wraps a non-Docker OCI image in the image struct will silently produce an artifact that cannot be pushed cross-repository.
Version: v0.20.7