{"record":{"id":"7a3f47e78439b8b8","repo":"docker/cli","slug":"s-has-no-payload","errorCode":null,"errorMessage":"%s has no payload","messagePattern":"(.+?) has no payload","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"cli/manifest/types/types.go","lineNumber":85,"sourceCode":"\t\trefs := i.OCIManifest.References()\n\t\tdigests = make([]digest.Digest, 0, len(refs))\n\t\tfor _, descriptor := range refs {\n\t\t\tdigests = append(digests, descriptor.Digest)\n\t\t}\n\t}\n\treturn digests\n}\n\n// Payload returns the media type and bytes for the manifest\nfunc (i ImageManifest) Payload() (string, []byte, error) {\n\t// TODO: If available, read content from a content store by digest\n\tswitch {\n\tcase i.SchemaV2Manifest != nil:\n\t\treturn i.SchemaV2Manifest.Payload()\n\tcase i.OCIManifest != nil:\n\t\treturn i.OCIManifest.Payload()\n\tdefault:\n\t\treturn \"\", nil, fmt.Errorf(\"%s has no payload\", i.Ref)\n\t}\n}\n\n// References implements the distribution.Manifest interface. It delegates to\n// the underlying manifest.\nfunc (i ImageManifest) References() []distribution.Descriptor {\n\tswitch {\n\tcase i.SchemaV2Manifest != nil:\n\t\treturn i.SchemaV2Manifest.References()\n\tcase i.OCIManifest != nil:\n\t\treturn i.OCIManifest.References()\n\tdefault:\n\t\treturn nil\n\t}\n}\n\n// NewImageManifest returns a new ImageManifest object. The values for Platform\n// are initialized from those in the image","sourceCodeStart":67,"sourceCodeEnd":103,"githubUrl":"https://github.com/docker/cli/blob/4f84911bfe8811e9b028e4b1fee8e7510be79387/cli/manifest/types/types.go#L67-L103","documentation":"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.","triggerScenarios":"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).","commonSituations":"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.","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."],"exampleFix":"// before: Payload() panics-free but errors because no manifest set\nim := types.ImageManifest{Ref: ref, Descriptor: desc}\nmt, raw, err := im.Payload()\n\n// after: build through the constructor so the manifest is attached\nim := types.NewOCIImageManifest(ref, desc, deserializedOCI)\nmt, raw, err := im.Payload()","handlingStrategy":"validation","validationCode":"// Ensure a manifest is attached before requesting its payload\nif im.SchemaV2Manifest == nil && im.OCIManifest == nil {\n    return fmt.Errorf(\"ref %s has no manifest object; refusing Payload()\", im.Ref)\n}\nmt, raw, err := im.Payload()","typeGuard":"// hasPayload narrows an ImageManifest to one that is safe to call Payload on\nfunc hasPayload(im types.ImageManifest) bool {\n    return im.SchemaV2Manifest != nil || im.OCIManifest != nil\n}","tryCatchPattern":null,"preventionTips":["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."],"tags":["manifest","api-misuse","validation"],"backgroundTag":null,"analyzedSha":"4f84911bfe8811e9b028e4b1fee8e7510be79387","analyzedAt":"2026-08-07T12:15:29.814Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-15T23:17:13.987Z"}