docker/cli · error

no tag specified for

Error message

no tag specified for %s

What it means

Returned by validateTag() in `docker trust sign` when the supplied image reference has no tag component and is not a digest reference. The command requires IMAGE:TAG because trust data is keyed per tag; signing an untagged 'latest-ish' reference is ambiguous and refused. %s is imgRefAndAuth.Name().

Solutions

  1. Append an explicit tag: `docker trust sign <image>:<tag>`.
  2. If the tag lives in a shell variable, verify it is non-empty before invoking the command.
  3. Tag the image first with `docker tag <image> <image>:<tag>` if needed, then sign.

Example fix

// before
$ docker trust sign registry.example.com/app
Error: no tag specified for registry.example.com/app

// after
$ docker trust sign registry.example.com/app:v1
Defensive patterns

Strategy: validation

Validate before calling

// Validate an explicit tag is present before invoking sign
import "github.com/distribution/reference"

func ensureTagged(imageRef string) error {
    ref, err := reference.ParseNormalizedNamed(imageRef)
    if err != nil { return err }
    if _, ok := ref.(reference.NamedTagged); !ok {
        return fmt.Errorf("reference %s has no tag; pass <image>:<tag>", imageRef)
    }
    return nil
}

Type guard

// Type guard narrowing a parsed reference to one carrying a tag
func hasTag(r reference.Reference) bool {
    _, ok := r.(reference.NamedTagged)
    return ok
}

Prevention

When it happens

Trigger: Invoking `docker trust sign myimage` (no tag) or `docker trust sign registry.example.com/myrepo` where the reference parser yields an empty Tag() and empty Digest(). Distinct from the digest case (sign.go:139) which returns 'cannot use a digest reference'.

Common situations: User habitually omits tags expecting 'latest'; copy-pasting a repository URL without a tag; CI script interpolating an empty $TAG variable.

Related errors


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

Appendix: source

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

	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)
	return err
}

func createTarget(notaryRepo notaryclient.Repository, tag string) (notaryclient.Target, error) {
	target := &notaryclient.Target{}
	var err error
	if tag == "" {
		return *target, errors.New("no tag specified")
	}
	target.Name = tag
	target.Hashes, target.Length, err = getSignedManifestHashAndSize(notaryRepo, tag)
	return *target, err

View on GitHub (pinned to 4f84911bfe)