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
- Push the source image (or upload the blob) to the target registry first so it exists.
- Verify push permissions on both source and target repositories.
- Retry on transient transport errors.
- 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
- Push layers before attempting cross-repo mounts.
- Verify push permissions on both repos.
- Retry only on transport-class errors.
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
- failed to put manifest
- error: username is required
- error: password is required
- conflicting options: cannot specify both --password and…
- the --password-stdin option requires --username to be set
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)