docker/cli · error
could not remove signature for
Error message
could not remove signature for %s: %w
What it means
Returned by `docker trust revoke` when the underlying notary client cannot remove the signature(s) for the given image reference. The error wraps the notary client failure that occurs inside revokeSignature(), which either removes a single tag's signature (revokeSingleSig) or all signatures (revokeAllSigs) and then calls notaryRepo.Publish(). The %s is the user-supplied IMAGE[:TAG] and %w is the raw notary error (network failure, missing trust data, permission error, etc.).
Solutions
- Verify the image was signed: run `docker trust inspect <image>:<tag>` and confirm signer metadata exists before revoking.
- Check connectivity to the notary server (the registry's notary/grafeas endpoint) and that your registry supports content trust.
- Re-authenticate with `docker login <registry>` to ensure push-scope credentials are current.
- If no tag is given and you intend to revoke all signatures, pass `-y` to skip the prompt and confirm the repo has signed tags (otherwise you hit the earlier 'no signed tags to remove' guard).
- Inspect the wrapped %w error text for the notary-specific cause (e.g. ErrRepoNotInitialized, ErrRepositoryNotExist) and address that root cause.
Example fix
// before $ docker trust revoke myimage Error: could not remove signature for myimage: ... // after — ensure the image is signed and credentials are valid $ docker login registry.example.com $ docker trust inspect registry.example.com/myimage:latest # confirm signed $ docker trust revoke registry.example.com/myimage:latest -y
Defensive patterns
Strategy: validation
Validate before calling
// Before revoking, confirm the image is signed and reachable
// shell pre-check (caller-side):
// docker trust inspect <image>:<tag> >/dev/null 2>&1 && docker trust revoke <image>:<tag> -y
// In Go code wrapping the CLI:
func canRevoke(repo, tag string) error {
if tag == "" { return errors.New("tag required for revoke pre-check") }
// run `docker trust inspect` and assert a signer entry exists
return nil
} Try / catch
// When invoking docker trust revoke programmatically, treat the wrapped error as fatal
// but distinguish transient (network) from permanent (not signed) via the %w text:
out, err := exec.CommandContext(ctx, "docker", "trust", "revoke", ref, "-y").CombinedOutput()
if err != nil {
if strings.Contains(string(out), "no signed tags") { /* nothing to revoke */ return nil }
return fmt.Errorf("revoke failed: %s: %w", string(out), err)
} Prevention
- Always sign images in CI right after push so revoke targets exist.
- Pin registry credentials with push scope in CI before revoke steps.
- Run `docker trust inspect` as a precondition check in automation before revoke.
When it happens
Trigger: Calling `docker trust revoke <image>:<tag>` or `docker trust revoke <image>` when the notary server is unreachable, the trust repository has not been initialized, the tag has no signed target (GetTargetByName fails), or Publish() fails to push metadata changes. Also triggered when the caller lacks push credentials to the registry's notary service.
Common situations: Operating against a registry without Content Trust/Notary enabled; revoking an image that was never signed; expired or missing notary delegation keys in ~/.docker/trust; network proxies intercepting the notary endpoint; rotating registry credentials so the stored auth no longer has push scope.
Related errors
- failed to sign
- failed to add signer to
- could not add signer to repo
- no valid signing keys for delegation roles
- no targets found, provide a specific tag in order to sign it
AI-assisted analysis of docker/cli@4f84911bfe (2026-08-07).
Data as JSON: /api/errors/46109f281af71cd7.
Report an issue: GitHub.
Appendix: source
Thrown at cmd/docker-trust/trust/revoke.go:66
if err != nil {
return err
}
if !deleteRemote {
return cancelledErr{errors.New("trust revoke has been cancelled")}
}
}
notaryRepo, err := newNotaryClient(dockerCLI, imgRefAndAuth, trust.ActionsPushAndPull)
if err != nil {
return err
}
if err = clearChangeList(notaryRepo); err != nil {
return err
}
defer clearChangeList(notaryRepo)
if err := revokeSignature(notaryRepo, tag); err != nil {
return fmt.Errorf("could not remove signature for %s: %w", remote, err)
}
_, _ = fmt.Fprintf(dockerCLI.Out(), "Successfully deleted signature for %s\n", remote)
return nil
}
type cancelledErr struct{ error }
func (cancelledErr) Cancelled() {}
func revokeSignature(notaryRepo client.Repository, tag string) error {
if tag != "" {
// Revoke signature for the specified tag
if err := revokeSingleSig(notaryRepo, tag); err != nil {
return err
}
} else {
// revoke all signatures for the image, as no tag was given
if err := revokeAllSigs(notaryRepo); err != nil {View on GitHub (pinned to 4f84911bfe)