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
- Pull the latest trust metadata before signing: re-run `docker trust sign` after `docker pull <image>` to refresh local state.
- Ensure the required delegation private key is present in ~/.docker/trust/private; import it if signing from a new host.
- Confirm push auth with `docker login <registry>`.
- Read the wrapped %w for the specific notary error (ErrInvalidRole, threshold-not-met, etc.) and address it (e.g. re-add the signer key).
- 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
- Pull the image immediately before signing to refresh local trust metadata.
- Keep delegation private keys on the signing host under ~/.docker/trust/private.
- Use the same host/key for repeated signs to avoid delegation conflicts.
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
- could not add signer to repo
- no valid signing keys for delegation roles
- could not remove signature for
- could not add signer to repo
- error removing signer from
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)