docker/cli · error

failed to sign

Error message

failed to sign %s:%s: %w

What it means

Returned by `docker trust sign IMAGE:TAG` from signAndPublishToTarget() when either AddToAllSignableRoles() (adding the target to all signable delegation roles) or the subsequent notaryRepo.Publish() fails. The first %s is the repository name (imgRefAndAuth.RepoInfo().Name.Name()), the second %s is the tag, and %w is the underlying notary error.

Solutions

  1. Pull the latest trust metadata before signing: re-run `docker trust sign` after `docker pull <image>` to refresh local state.
  2. Ensure the required delegation private key is present in ~/.docker/trust/private; import it if signing from a new host.
  3. Confirm push auth with `docker login <registry>`.
  4. Read the wrapped %w for the specific notary error (ErrInvalidRole, threshold-not-met, etc.) and address it (e.g. re-add the signer key).
  5. If the trust repo is corrupted, rotate by re-initializing with the correct root key.

Example fix

// before
$ docker trust sign registry.example.com/app:v1
Error: failed to sign registry.example.com/app:v1: ...

// after — load the delegation key on this host then re-sign
$ docker trust key load --key alice.key
$ docker trust sign registry.example.com/app:v1
Defensive patterns

Strategy: retry

Validate before calling

// Pre-flight: ensure the local image exists and trust keys are present
//   docker image inspect <image>            # local image exists
//   ls ~/.docker/trust/private/*.key        # delegation key present
//   docker trust inspect <image>:<tag>      # trust repo reachable

Try / catch

// Signing can fail on stale metadata; pull then retry once
for attempt := 0; attempt < 2; attempt++ {
    out, err := exec.CommandContext(ctx, "docker", "trust", "sign", ref).CombinedOutput()
    if err == nil { break }
    if attempt == 0 && strings.Contains(string(out), "metadata") {
        _ = exec.CommandContext(ctx, "docker", "pull", ref).Run() // refresh
        continue
    }
    return fmt.Errorf("sign failed: %s: %w", out, err)
}

Prevention

When it happens

Trigger: Running `docker trust sign <repo>:<tag>` where the local trust metadata is stale or conflicts with remote, the signer's delegation key is missing, the threshold for a delegation role cannot be met, or Publish() cannot push (network, auth, or metadata validation failure).

Common situations: Signing after pulling an image whose trust data was updated by another signer (metadata conflict); using a different machine than where the delegation keys live; registry notary service down or returning 4xx; clock skew between client and notary server breaking metadata expiry checks.

Related errors


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

Appendix: source

Thrown at cmd/docker-trust/trust/sign.go:129

		}
	}
	return signAndPublishToTarget(dockerCLI.Out(), imgRefAndAuth, notaryRepo, target)
}

func signAndPublishToTarget(out io.Writer, imgRefAndAuth trust.ImageRefAndAuth, notaryRepo notaryclient.Repository, target notaryclient.Target) error {
	tag := imgRefAndAuth.Tag()
	_, _ = fmt.Fprintln(out, "Signing and pushing trust metadata for", imgRefAndAuth.Name())
	existingSigInfo, err := getExistingSignatureInfoForReleasedTag(notaryRepo, tag)
	if err != nil {
		return err
	}
	err = trust.AddToAllSignableRoles(notaryRepo, &target)
	if err == nil {
		prettyPrintExistingSignatureInfo(out, existingSigInfo)
		err = notaryRepo.Publish()
	}
	if err != nil {
		return fmt.Errorf("failed to sign %s:%s: %w", imgRefAndAuth.RepoInfo().Name.Name(), tag, err)
	}
	_, _ = fmt.Fprintf(out, "Successfully signed %s:%s\n", imgRefAndAuth.RepoInfo().Name.Name(), tag)
	return nil
}

func validateTag(imgRefAndAuth trust.ImageRefAndAuth) error {
	tag := imgRefAndAuth.Tag()
	if tag == "" {
		if imgRefAndAuth.Digest() != "" {
			return errors.New("cannot use a digest reference for IMAGE:TAG")
		}
		return fmt.Errorf("no tag specified for %s", imgRefAndAuth.Name())
	}
	return nil
}

func checkLocalImageExistence(ctx context.Context, apiClient client.APIClient, imageName string) error {
	_, err := apiClient.ImageInspect(ctx, imageName)

View on GitHub (pinned to 4f84911bfe)