docker/cli · error
failed to put manifest
Error message
failed to put manifest %s: %w
What it means
Returned by client.PutManifest when manifestService.Put (distribution Put) returns a non-nil error while uploading a manifest to the registry. The reference and underlying error are wrapped with %w. This is the final step of pushing an image manifest.
Solutions
- Ensure all referenced blobs/layers are already pushed to the target repository.
- Inspect the wrapped error: 401/403 -> auth, 400 -> manifest/tag format, 4xx -> schema.
- Use a valid reference (lowercase repo, allowed tag chars).
- Retry on transient transport failures.
Example fix
// before: layers not uploaded first client.PutManifest(ctx, ref, manifest) // 400 manifest blob unknown // after: push layers, then manifest client.MountBlob(ctx, layerSrc, ref) // or UploadBlob client.PutManifest(ctx, ref, manifest)
Defensive patterns
Strategy: try-catch
Validate before calling
// ensure all manifest descriptors' blobs exist before Put
for _, d := range manifest.References() {
if _, err := repo.Blobs(ctx).Stat(ctx, d.Digest); err != nil { return err }
} Try / catch
if errdefs.IsUnauthorized(err) { refreshCreds(); retry }
if errdefs.IsInvalidParameter(err) { fixManifestOrRef() } Prevention
- Upload all referenced layers/digests before the manifest.
- Validate repo/tag naming (lowercase, allowed chars).
- Classify via the wrapped error before retrying.
When it happens
Trigger: Pushing a manifest (PutManifest) when the registry rejects the PUT — manifest invalid/unknown schema, missing referenced blobs/layers, digest mismatch, authorization denied, name/tag validation error, or transport failure.
Common situations: Pushing a manifest before its layers are uploaded; tag naming violation (uppercase, _ vs .); registry quota/permission denied; manifest schema unsupported by registry; network error mid-upload.
Related errors
- failed to mount blob
- manifest must have an OS and Architecture to be pushed to a…
- cannot use source images from a different registry than the…
- error mounting to
- is a manifest list
AI-assisted analysis of docker/cli@4f84911bfe (2026-08-07).
Data as JSON: /api/errors/6dc49a17d9fbbf8a.
Report an issue: GitHub.
Appendix: source
Thrown at internal/registryclient/client.go:117
repoEndpoint.actions = []string{"pull", "push"}
repo, err := c.getRepositoryForReference(ctx, ref, repoEndpoint)
if err != nil {
return "", err
}
manifestService, err := repo.Manifests(ctx)
if err != nil {
return "", err
}
_, opts, err := getManifestOptionsFromReference(ref)
if err != nil {
return "", err
}
dgst, err := manifestService.Put(ctx, manifest, opts...)
if err != nil {
return dgst, fmt.Errorf("failed to put manifest %s: %w", ref, err)
}
return dgst, nil
}
func (c *client) getRepositoryForReference(ctx context.Context, ref reference.Named, repoEndpoint repositoryEndpoint) (distribution.Repository, error) {
repoName, err := reference.WithName(repoEndpoint.repoName)
if err != nil {
return nil, fmt.Errorf("failed to parse repo name from %s: %w", ref, err)
}
httpTransport, err := c.getHTTPTransportForRepoEndpoint(ctx, repoEndpoint)
if err != nil {
if !strings.Contains(err.Error(), "server gave HTTP response to HTTPS client") {
return nil, err
}
if !repoEndpoint.endpoint.TLSConfig.InsecureSkipVerify {
return nil, httpProtoError{cause: err}
}
// --insecure was set; fall back to plain HTTPView on GitHub (pinned to 4f84911bfe)