docker/cli · error

failed to mount blob

Error message

failed to mount blob %s to %s: %w

What it means

Returned by client.MountBlob when repository.Blobs(ctx).Create with WithMountFrom(sourceRef) returns an error that is neither distribution.ErrBlobMounted nor nil. A cross-repository blob mount is attempted when pushing; only the ErrBlobMounted success type is expected, anything else (blob unknown, permission, network) is wrapped here.

Solutions

  1. Push the source image (or upload the blob) to the target registry first so it exists.
  2. Verify push permissions on both source and target repositories.
  3. Retry on transient transport errors.
  4. Use a registry that supports cross-repo blob mount (distribution >= v2).

Example fix

// before: blob not present in target, mount fails
client.MountBlob(ctx, srcRef, tgtRef)
// after: push the source image so the layer exists, then mount
client.Push(ctx, srcImage)  // makes blob available
client.MountBlob(ctx, srcRef, tgtRef)
Defensive patterns

Strategy: try-catch

Validate before calling

// confirm the source blob exists in target repo before mounting
if _, err := repo.Blobs(ctx).Stat(ctx, sourceDigest); err != nil { /* upload first */ }

Try / catch

var bne distribution.ErrBlobUnknown
if errors.As(err, &bne) { uploadBlobFirst(); retry }

Prevention

When it happens

Trigger: Pushing an image and attempting to mount a layer from a source repo to a target repo when the registry denies the mount or the source blob is missing — typically missing cross-repo mount permission, source digest not present, or transport error.

Common situations: Target registry lacks cross-repository mount support/permission; source blob was deleted/garbage-collected; pushing to a registry that requires the blob to exist first; network blip during mount.

Related errors


AI-assisted analysis of docker/cli@4f84911bfe (2026-08-07). Data as JSON: /api/errors/0dc30a1be42e91ce. Report an issue: GitHub.

Appendix: source

Thrown at internal/registryclient/client.go:85

// MountBlob into the registry, so it can be referenced by a manifest
func (c *client) MountBlob(ctx context.Context, sourceRef reference.Canonical, targetRef reference.Named) error {
	repoEndpoint, err := newDefaultRepositoryEndpoint(targetRef, c.insecureRegistry)
	if err != nil {
		return err
	}
	repoEndpoint.actions = []string{"pull", "push"}
	repo, err := c.getRepositoryForReference(ctx, targetRef, repoEndpoint)
	if err != nil {
		return err
	}
	lu, err := repo.Blobs(ctx).Create(ctx, distributionclient.WithMountFrom(sourceRef))
	switch err.(type) {
	case distribution.ErrBlobMounted:
		logrus.Debugf("mount of blob %s succeeded", sourceRef)
		return nil
	case nil:
	default:
		return fmt.Errorf("failed to mount blob %s to %s: %w", sourceRef, targetRef, err)
	}
	_ = lu.Cancel(ctx)
	logrus.Debugf("mount of blob %s created", sourceRef)
	return ErrBlobCreated{From: sourceRef, Target: targetRef}
}

// PutManifest sends the manifest to a registry and returns the new digest
func (c *client) PutManifest(ctx context.Context, ref reference.Named, manifest distribution.Manifest) (digest.Digest, error) {
	repoEndpoint, err := newDefaultRepositoryEndpoint(ref, c.insecureRegistry)
	if err != nil {
		return "", err
	}

	repoEndpoint.actions = []string{"pull", "push"}
	repo, err := c.getRepositoryForReference(ctx, ref, repoEndpoint)
	if err != nil {
		return "", err
	}

View on GitHub (pinned to 4f84911bfe)