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

  1. Always build ImageManifest via NewImageManifest or NewOCIImageManifest so the manifest object is attached.
  2. Before calling Payload, guard with a check: ensure SchemaV2Manifest or OCIManifest is non-nil.
  3. If loading from JSON, validate the file contains one of the manifest fields; re-fetch if absent.
  4. 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

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


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 image

View on GitHub (pinned to 4f84911bfe)