docker/cli · error
manifest must have an OS and Architecture to be pushed to a…
Error message
manifest %s must have an OS and Architecture to be pushed to a registry
What it means
Returned by `buildManifestList` (push.go:127-132) when a constituent manifest has `Descriptor.Platform == nil` or an empty OS/Architecture. A registry requires every manifest-list entry to declare a platform, so the push is aborted before any network call. This happens when an image was added without annotation and its source manifest lacked platform metadata.
Solutions
- Annotate each offending entry: `docker manifest annotate --os linux --arch amd64 list img`.
- Re-create the list using images that carry platform metadata.
- Inspect each member to find which one is missing platform info.
- Push each single-arch image separately if a manifest list is not required.
Example fix
# before docker manifest create mylist img-no-platform docker manifest push mylist # fails # after docker manifest annotate mylist img-no-platform --os linux --arch amd64 docker manifest push mylist
Defensive patterns
Strategy: validation
Validate before calling
// verify every member has platform metadata before pushing
for _, m := range manifests {
if m.Descriptor.Platform == nil ||
m.Descriptor.Platform.OS == "" ||
m.Descriptor.Platform.Architecture == "" {
return fmt.Errorf("member %s missing OS/Architecture; annotate before push", m.Ref)
}
} Type guard
func hasPlatform(m types.ImageManifest) bool {
p := m.Descriptor.Platform
return p != nil && p.OS != "" && p.Architecture != ""
} Try / catch
if err := runPush(ctx, cli, opts); err != nil {
if strings.Contains(err.Error(), "must have an OS and Architecture") {
// identify and annotate the offending member
return annotateMissingPlatforms(manifests)
}
return err
} Prevention
- Annotate every member with --os/--arch after create.
- Use source images that already carry platform metadata.
- Inspect each member before push to catch empty platforms.
When it happens
Trigger: Running `docker manifest create list img` where `img` is a single-arch image whose manifest has no platform, then `docker manifest push list` without annotating --os/--arch.
Common situations: Forgetting `docker manifest annotate --os --arch` after create, or adding an image from a registry that omits platform fields.
Related errors
- cannot use source images from a different registry than the…
- error mounting to
- manifest entry for image has unsupported os/arch combination
- failed to assemble ManifestDescriptor
- not found
AI-assisted analysis of docker/cli@4f84911bfe (2026-08-07).
Data as JSON: /api/errors/d3d4fb247f027d47.
Report an issue: GitHub.
Appendix: source
Thrown at cli/command/manifest/push.go:131
manifestPush, err := buildPutManifestRequest(imageManifest, targetRef)
if err != nil {
return req, err
}
req.mountRequests = append(req.mountRequests, manifestPush)
}
}
return req, nil
}
func buildManifestList(manifests []types.ImageManifest, targetRef reference.Named) (*manifestlist.DeserializedManifestList, error) {
targetRepo := reference.TrimNamed(targetRef)
descriptors := make([]manifestlist.ManifestDescriptor, 0, len(manifests))
for _, imageManifest := range manifests {
if imageManifest.Descriptor.Platform == nil ||
imageManifest.Descriptor.Platform.Architecture == "" ||
imageManifest.Descriptor.Platform.OS == "" {
return nil, fmt.Errorf("manifest %s must have an OS and Architecture to be pushed to a registry", imageManifest.Ref)
}
descriptor, err := buildManifestDescriptor(targetRepo, imageManifest)
if err != nil {
return nil, err
}
descriptors = append(descriptors, descriptor)
}
return manifestlist.FromDescriptors(descriptors)
}
func buildManifestDescriptor(targetRepo reference.Named, imageManifest types.ImageManifest) (manifestlist.ManifestDescriptor, error) {
manifestRepoHostname := reference.Domain(reference.TrimNamed(imageManifest.Ref))
targetRepoHostname := reference.Domain(reference.TrimNamed(targetRepo))
if manifestRepoHostname != targetRepoHostname {
return manifestlist.ManifestDescriptor{}, fmt.Errorf("cannot use source images from a different registry than the target image: %s != %s", manifestRepoHostname, targetRepoHostname)
}
View on GitHub (pinned to 4f84911bfe)