docker/cli · error
failed to sign
Error message
failed to sign %s:%s: %w
What it means
In PushTrustedReference (trust_push.go:139-146), after the target has been added and Publish() attempted, if any error remains it is wrapped as 'failed to sign <repo>:<tag>' and then passed through NotaryError for human-friendly mapping. This is the catch-all signing/publish failure for a trusted push - the underlying cause is in the wrapped error (could be ErrNoKeys, ErrInsufficientSignatures, network error during publish, etc.).
Solutions
- Read the wrapped (%w) underlying error first - it is mapped by NotaryError into a more specific message; address that root cause (e.g. import key if ErrNoKeys).
- Ensure a valid signing key for the targets/releases role is loaded locally ('docker trust key load').
- For delegation-based repos, confirm the pushing user holds one of the delegation keys whose ID is listed in the role's KeyIDs (check with 'docker trust inspect --pretty').
- Retry on transient network errors; if Publish partially uploaded metadata, the next attempt may need the server-side stale changelist cleared (clearChangeList is called in lookupTrustInfo).
- If initializing for the first time, confirm the root key passphrase (DOCKER_CONTENT_TRUST_ROOT_PASSPHRASE) is set.
Defensive patterns
Strategy: try-catch
Validate before calling
// Validate signing prerequisites before calling PushTrustedReference/Publish.
func preflightTrustedPush(repo client.Repository) error {
if _, err := repo.ListTargets(); err != nil {
// tolerate not-initialized/not-exist (PushTrustedReference bootstraps), surface the rest
if _, ok := err.(client.ErrRepositoryNotExist); !ok && _, ok2 := err.(client.ErrRepoNotInitialized); !ok2 {
return trust.NotaryError(gun, err)
}
}
return ensureSigningKeyAvailable(repo, os.Getenv("DOCKER_CONTENT_TRUST_REPOSITORY_PASSPHRASE"))
} Try / catch
if err := repo.Publish(); err != nil {
err = fmt.Errorf("failed to sign %s:%s: %w", gun, tag, err)
return trust.NotaryError(gun, err) // maps underlying type to a human message
} Prevention
- Pre-check that a signable role/key exists via GetSignableRoles before AddTarget.
- For delegation repos, confirm the pusher holds a listed delegation key ID.
- Set both ROOT and REPOSITORY passphrases for first-time initialization.
- Capture the wrapped underlying error to route to the right remediation (key vs network vs init).
When it happens
Trigger: repo.Publish() fails (network error uploading metadata to notary server); repo.AddTarget() / AddToAllSignableRoles() fails (no valid signing keys for delegation roles - 'no valid signing keys for delegation roles' from GetSignableRoles at trust.go:317); repo.Initialize() fails during first push; the underlying error is then mapped by NotaryError into one of the specific messages.
Common situations: First-time trusted push where repository initialization fails; CI environment without the signing key; delegation role configured but the pushing identity lacks any of the delegation keys; transient network error between client and notary server during the final Publish step; notary server out of disk or misconfigured.
Related errors
- error: could not produce valid signature for
- error: could not find signing keys for remote repository
- warning: potential malicious behavior - trust data version…
- warning: potential malicious behavior - trust data has…
- error: remote trust data does not exist for
AI-assisted analysis of docker/cli@4f84911bfe (2026-08-07).
Data as JSON: /api/errors/5843c5b5e4c018e6.
Report an issue: GitHub.
Appendix: source
Thrown at cmd/docker-trust/internal/trust/trust_push.go:144
// Initialize the notary repository with a remotely managed snapshot key
if err := repo.Initialize([]string{rootKeyID}, data.CanonicalSnapshotRole); err != nil {
return NotaryError(repoInfo.Name.Name(), err)
}
_, _ = fmt.Fprintf(ioStreams.Out(), "Finished initializing %q\n", repoInfo.Name.Name())
err = repo.AddTarget(notaryTarget, data.CanonicalTargetsRole)
case nil:
// already initialized and we have successfully downloaded the latest metadata
err = AddToAllSignableRoles(repo, notaryTarget)
default:
return NotaryError(repoInfo.Name.Name(), err)
}
if err == nil {
err = repo.Publish()
}
if err != nil {
err = fmt.Errorf("failed to sign %s:%s: %w", repoInfo.Name.Name(), tag, err)
return NotaryError(repoInfo.Name.Name(), err)
}
_, _ = fmt.Fprintf(ioStreams.Out(), "Successfully signed %s:%s\n", repoInfo.Name.Name(), tag)
return nil
}
View on GitHub (pinned to 4f84911bfe)