docker/cli · error
has no payload
Error message
%s has no payload
What it means
Returned by ImageManifest.Payload (cli/manifest/types/types.go:85) when neither SchemaV2Manifest nor OCIManifest is populated on the ImageManifest. Payload is supposed to return the media type + raw bytes of a manifest, but the struct is effectively empty (only Ref/Descriptor/Raw set), so there is nothing to serialize. The message prints i.Ref to identify which reference is affected.
Solutions
- Always build ImageManifest via NewImageManifest or NewOCIImageManifest so the manifest object is attached.
- Before calling Payload, guard with a check: ensure SchemaV2Manifest or OCIManifest is non-nil.
- If loading from JSON, validate the file contains one of the manifest fields; re-fetch if absent.
- Avoid persisting half-populated ImageManifest structs with Save.
Example fix
// before: Payload() panics-free but errors because no manifest set
im := types.ImageManifest{Ref: ref, Descriptor: desc}
mt, raw, err := im.Payload()
// after: build through the constructor so the manifest is attached
im := types.NewOCIImageManifest(ref, desc, deserializedOCI)
mt, raw, err := im.Payload() Defensive patterns
Strategy: validation
Validate before calling
// Ensure a manifest is attached before requesting its payload
if im.SchemaV2Manifest == nil && im.OCIManifest == nil {
return fmt.Errorf("ref %s has no manifest object; refusing Payload()", im.Ref)
}
mt, raw, err := im.Payload() Type guard
// hasPayload narrows an ImageManifest to one that is safe to call Payload on
func hasPayload(im types.ImageManifest) bool {
return im.SchemaV2Manifest != nil || im.OCIManifest != nil
} Prevention
- Always build ImageManifest via NewImageManifest / NewOCIImageManifest.
- Never construct ImageManifest with a struct literal that omits the manifest fields.
- Unit-test Payload() against constructors, not hand-built structs.
When it happens
Trigger: Calling .Payload() on an ImageManifest constructed without passing a manifest into NewImageManifest/NewOCIImageManifest — e.g. one built by hand with only Descriptor, or one deserialized from a JSON file that omits both manifest fields (which is exactly the legacy case handled in store.go that then calls Payload).
Common situations: Constructing an ImageManifest directly with a struct literal (skipping the constructor), reading a minimal/cached manifest JSON that only stored Descriptor, or a code path that adds an entry to a manifest list via Save without ever attaching the underlying manifest object.
Related errors
- refusing to amend an existing manifest list with no --amend…
- annotate: error parsing name for manifest list
- annotate: error parsing name for manifest
- manifest entry for image has unsupported os/arch combination
- error parsing name for manifest list
AI-assisted analysis of docker/cli@4f84911bfe (2026-08-07).
Data as JSON: /api/errors/7a3f47e78439b8b8.
Report an issue: GitHub.
Appendix: source
Thrown at cli/manifest/types/types.go:85
refs := i.OCIManifest.References()
digests = make([]digest.Digest, 0, len(refs))
for _, descriptor := range refs {
digests = append(digests, descriptor.Digest)
}
}
return digests
}
// Payload returns the media type and bytes for the manifest
func (i ImageManifest) Payload() (string, []byte, error) {
// TODO: If available, read content from a content store by digest
switch {
case i.SchemaV2Manifest != nil:
return i.SchemaV2Manifest.Payload()
case i.OCIManifest != nil:
return i.OCIManifest.Payload()
default:
return "", nil, fmt.Errorf("%s has no payload", i.Ref)
}
}
// References implements the distribution.Manifest interface. It delegates to
// the underlying manifest.
func (i ImageManifest) References() []distribution.Descriptor {
switch {
case i.SchemaV2Manifest != nil:
return i.SchemaV2Manifest.References()
case i.OCIManifest != nil:
return i.OCIManifest.References()
default:
return nil
}
}
// NewImageManifest returns a new ImageManifest object. The values for Platform
// are initialized from those in the imageView on GitHub (pinned to 4f84911bfe)