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

  1. Ensure all referenced blobs/layers are already pushed to the target repository.
  2. Inspect the wrapped error: 401/403 -> auth, 400 -> manifest/tag format, 4xx -> schema.
  3. Use a valid reference (lowercase repo, allowed tag chars).
  4. 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

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


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 HTTP

View on GitHub (pinned to 4f84911bfe)