{"record":{"id":"8ca52da4439d91f5","repo":"docker/cli","slug":"cannot-use-a-digest-reference-for-image-tag","errorCode":null,"errorMessage":"cannot use a digest reference for IMAGE:TAG","messagePattern":"cannot use a digest reference for IMAGE:TAG","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"cmd/docker-trust/trust/revoke.go","lineNumber":44,"sourceCode":"\t\tArgs:  cli.ExactArgs(1),\n\t\tRunE: func(cmd *cobra.Command, args []string) error {\n\t\t\treturn revokeTrust(cmd.Context(), dockerCLI, args[0], options)\n\t\t},\n\t\tDisableFlagsInUseLine: true,\n\t}\n\tflags := cmd.Flags()\n\tflags.BoolVarP(&options.forceYes, \"yes\", \"y\", false, \"Do not prompt for confirmation\")\n\treturn cmd\n}\n\nfunc revokeTrust(ctx context.Context, dockerCLI command.Cli, remote string, options revokeOptions) error {\n\timgRefAndAuth, err := trust.GetImageReferencesAndAuth(ctx, authResolver(dockerCLI), remote)\n\tif err != nil {\n\t\treturn err\n\t}\n\ttag := imgRefAndAuth.Tag()\n\tif imgRefAndAuth.Tag() == \"\" && imgRefAndAuth.Digest() != \"\" {\n\t\treturn errors.New(\"cannot use a digest reference for IMAGE:TAG\")\n\t}\n\tif imgRefAndAuth.Tag() == \"\" && !options.forceYes {\n\t\tdeleteRemote, err := prompt.Confirm(ctx, dockerCLI.In(), dockerCLI.Out(), fmt.Sprintf(\"Confirm you would like to delete all signature data for %s?\", remote))\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\t\tif !deleteRemote {\n\t\t\treturn cancelledErr{errors.New(\"trust revoke has been cancelled\")}\n\t\t}\n\t}\n\n\tnotaryRepo, err := newNotaryClient(dockerCLI, imgRefAndAuth, trust.ActionsPushAndPull)\n\tif err != nil {\n\t\treturn err\n\t}\n\n\tif err = clearChangeList(notaryRepo); err != nil {\n\t\treturn err","sourceCodeStart":26,"sourceCodeEnd":62,"githubUrl":"https://github.com/docker/cli/blob/4f84911bfe8811e9b028e4b1fee8e7510be79387/cmd/docker-trust/trust/revoke.go#L26-L62","documentation":"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.","triggerScenarios":"Running 'docker trust revoke repo/image@sha256:...' — the reference parses as Digested with no tag, hitting the guard at revoke.go:43.","commonSituations":"Pasting a digest reference pulled from an inspect/manifest command into a revoke call; CI scripts that canonicalize to digests before revoking.","solutions":["Revoke by tag instead: 'docker trust revoke repo/image:tag'.","If you want to revoke all signatures, pass a repository name without a tag and confirm the prompt.","Resolve the digest back to a tag via 'docker image ls' or the registry before revoking."],"exampleFix":"# before: docker trust revoke myrepo/img@sha256:abcd...\n# after:  docker trust revoke myrepo/img:v1","handlingStrategy":"validation","validationCode":"// Reject digest references before calling revokeTrust\nfunc validateRevokeRef(ref trust.ImageRefAndAuth) error {\n\tif ref.Tag() == \"\" && ref.Digest() != \"\" {\n\t\treturn errors.New(\"cannot use a digest reference for IMAGE:TAG; pass a tag\")\n\t}\n\treturn nil\n}","typeGuard":"// Ensure the reference is taggable for revocation\nfunc hasTagForRevoke(ref trust.ImageRefAndAuth) bool {\n\treturn ref.Tag() != \"\"\n}","tryCatchPattern":null,"preventionTips":["Pass a tag (repo:tag) to docker trust revoke, not a digest.","To revoke everything, pass the repo name without tag and confirm the prompt.","Validate the reference shape in scripts before invoking revoke."],"tags":["trust","notary","revoke","digest","reference"],"backgroundTag":null,"analyzedSha":"4f84911bfe8811e9b028e4b1fee8e7510be79387","analyzedAt":"2026-08-07T12:15:29.814Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-15T23:17:13.987Z"}