docker/cli · error

failed to add signer to

Error message

failed to add signer to: %s

What it means

Returned by `docker trust signer add` (addSigner) as an aggregate error when one or more of the listed REPOSITORY targets failed during addSignerToRepo(). The function iterates all repos, collects failures into errRepos, prints each underlying error to stderr, and returns this summary listing the failing repositories joined by ', '. %s is that comma-joined list.

Solutions

  1. Read the per-repo errors printed to stderr just before this summary — they contain the real cause for each repo.
  2. Retry signer add only against the failing repositories once their individual issues (auth, init) are resolved.
  3. Verify push credentials and notary reachability for each registry host involved.
  4. Confirm the public key file is valid (see ingestPublicKeys errors) so all repos get a fair attempt.

Example fix

// before
$ docker trust signer add alice reg1.io/app reg2.io/app --key alice.pub
Adding signer "alice" to reg2.io/app...
<per-repo error>
Error: failed to add signer to: reg2.io/app

// after — fix reg2 auth/init then retry just that repo
$ docker login reg2.io
$ docker trust signer add alice reg2.io/app --key alice.pub
Defensive patterns

Strategy: try-catch

Validate before calling

// Pre-check each repo is reachable and push-authed before bulk signer add
func preCheckRepos(repos []string) ([]string, error) {
    var ok []string
    for _, r := range repos {
        if out, err := exec.Command("docker", "trust", "inspect", r).CombinedOutput(); err != nil {
            log.Printf("skip %s: %s", r, out); continue
        }
        ok = append(ok, r)
    }
    if len(ok) == 0 { return nil, errors.New("no reachable repos") }
    return ok, nil
}

Try / catch

// Bulk add: parse the aggregate failure list and retry the survivors individually
out, err := exec.CommandContext(ctx, "docker", "trust", "signer", "add", name).CombinedOutput() // + repos, --key
if err != nil {
    // out already contains per-repo errors on stderr; surface them
    return fmt.Errorf("partial signer add failed:\n%s", out)
}

Prevention

When it happens

Trigger: Running `docker trust signer add <name> <repo1> <repo2> <repo3> --key k.pub` where at least one repo fails (notary init error, publish error, network, auth). Each individual repo error is printed first; this message names which repos failed overall.

Common situations: Bulk-adding a signer across many repos where some repos are on a different registry, some lack push perms, or some are uninitialized and init fails.

Related errors


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

Appendix: source

Thrown at cmd/docker-trust/trust/signer_add.go:77

	if options.keys.Len() == 0 {
		return errors.New("path to a public key must be provided using the `--key` flag")
	}
	signerPubKeys, err := ingestPublicKeys(options.keys.GetSlice())
	if err != nil {
		return err
	}
	var errRepos []string
	for _, repoName := range options.repos {
		_, _ = fmt.Fprintf(dockerCLI.Out(), "Adding signer \"%s\" to %s...\n", signerName, repoName)
		if err := addSignerToRepo(ctx, dockerCLI, signerName, repoName, signerPubKeys); err != nil {
			_, _ = fmt.Fprintln(dockerCLI.Err(), err.Error()+"\n")
			errRepos = append(errRepos, repoName)
		} else {
			_, _ = fmt.Fprintf(dockerCLI.Out(), "Successfully added signer: %s to %s\n\n", signerName, repoName)
		}
	}
	if len(errRepos) > 0 {
		return fmt.Errorf("failed to add signer to: %s", strings.Join(errRepos, ", "))
	}
	return nil
}

func addSignerToRepo(ctx context.Context, dockerCLI command.Cli, signerName string, repoName string, signerPubKeys []data.PublicKey) error {
	imgRefAndAuth, err := trust.GetImageReferencesAndAuth(ctx, authResolver(dockerCLI), repoName)
	if err != nil {
		return err
	}

	notaryRepo, err := newNotaryClient(dockerCLI, imgRefAndAuth, trust.ActionsPushAndPull)
	if err != nil {
		return trust.NotaryError(imgRefAndAuth.Reference().Name(), err)
	}

	if _, err = notaryRepo.ListTargets(); err != nil {
		switch err.(type) {
		case client.ErrRepoNotInitialized, client.ErrRepositoryNotExist:

View on GitHub (pinned to 4f84911bfe)