docker/cli · error

cannot use a digest reference for IMAGE:TAG

Error message

cannot use a digest reference for IMAGE:TAG

What it means

Returned by revokeTrust when the image reference carries a digest but no tag (Tag()=='' && Digest()!=''). Trust revocation operates on tags — it removes the signature entry for a named tag — so a bare digest reference has no tag to revoke and is rejected before contacting the Notary server.

Solutions

  1. Revoke by tag instead: 'docker trust revoke repo/image:tag'.
  2. If you want to revoke all signatures, pass a repository name without a tag and confirm the prompt.
  3. Resolve the digest back to a tag via 'docker image ls' or the registry before revoking.

Example fix

# before: docker trust revoke myrepo/img@sha256:abcd...
# after:  docker trust revoke myrepo/img:v1
Defensive patterns

Strategy: validation

Validate before calling

// Reject digest references before calling revokeTrust
func validateRevokeRef(ref trust.ImageRefAndAuth) error {
	if ref.Tag() == "" && ref.Digest() != "" {
		return errors.New("cannot use a digest reference for IMAGE:TAG; pass a tag")
	}
	return nil
}

Type guard

// Ensure the reference is taggable for revocation
func hasTagForRevoke(ref trust.ImageRefAndAuth) bool {
	return ref.Tag() != ""
}

Prevention

When it happens

Trigger: Running 'docker trust revoke repo/image@sha256:...' — the reference parses as Digested with no tag, hitting the guard at revoke.go:43.

Common situations: Pasting a digest reference pulled from an inspect/manifest command into a revoke call; CI scripts that canonicalize to digests before revoking.

Related errors


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

Appendix: source

Thrown at cmd/docker-trust/trust/revoke.go:44

		Args:  cli.ExactArgs(1),
		RunE: func(cmd *cobra.Command, args []string) error {
			return revokeTrust(cmd.Context(), dockerCLI, args[0], options)
		},
		DisableFlagsInUseLine: true,
	}
	flags := cmd.Flags()
	flags.BoolVarP(&options.forceYes, "yes", "y", false, "Do not prompt for confirmation")
	return cmd
}

func revokeTrust(ctx context.Context, dockerCLI command.Cli, remote string, options revokeOptions) error {
	imgRefAndAuth, err := trust.GetImageReferencesAndAuth(ctx, authResolver(dockerCLI), remote)
	if err != nil {
		return err
	}
	tag := imgRefAndAuth.Tag()
	if imgRefAndAuth.Tag() == "" && imgRefAndAuth.Digest() != "" {
		return errors.New("cannot use a digest reference for IMAGE:TAG")
	}
	if imgRefAndAuth.Tag() == "" && !options.forceYes {
		deleteRemote, err := prompt.Confirm(ctx, dockerCLI.In(), dockerCLI.Out(), fmt.Sprintf("Confirm you would like to delete all signature data for %s?", remote))
		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

View on GitHub (pinned to 4f84911bfe)