docker/cli · error
could not parse public key from file
Error message
could not parse public key from file: %s: %w
What it means
Returned by ingestPublicKeys() in `docker trust signer add` when the file was opened and read successfully but tufutils.ParsePEMPublicKey() cannot parse the bytes as a valid PEM-encoded public key. %s is the offending file path, %w is the parse error. This means the file is reachable and readable but is not a valid notary public key.
Solutions
- Export the public key in the correct PEM format expected by notary (use `docker trust key generate` to produce a compatible pair).
- Confirm you are passing the .pub file, not the private key.
- Validate the PEM structure manually (BEGIN/END PUBLIC KEY blocks, base64 intact).
- Regenerate the key pair with `docker trust key generate <name>` if the existing one is corrupt or wrong-format.
Example fix
// before $ docker trust signer add alice reg.io/app --key alice-private.pem Error: could not parse public key from file: alice-private.pem: ... // after — generate a proper pair and pass the public key $ docker trust key generate alice # produces alice-*.pub and a private key $ docker trust signer add alice reg.io/app --key alice-<id>.pub
Defensive patterns
Strategy: validation
Validate before calling
// Validate the PEM is a parseable public key before invoking signer add
import "encoding/pem"
func validatePEMPublicKey(path string) error {
b, err := os.ReadFile(path)
if err != nil { return err }
block, _ := pem.Decode(b)
if block == nil { return errors.New("not a PEM file") }
if !strings.Contains(block.Type, "PUBLIC KEY") {
return fmt.Errorf("PEM type %s is not a public key", block.Type)
}
return nil
} Type guard
func isPEMPublicKey(b []byte) bool {
block, _ := pem.Decode(b)
if block == nil { return false }
return strings.Contains(block.Type, "PUBLIC KEY")
} Prevention
- Generate keys with `docker trust key generate` to guarantee a compatible format.
- Pass the .pub file, never the private key.
- Lint PEM blocks in CI before the signer-add step.
When it happens
Trigger: Passing `--key <file>` whose contents are not a PEM public key — e.g. a private key file, a PEM with an unsupported algorithm, a corrupted/truncated PEM, a non-PEM format (OpenSSH, JWK, DER), or a text file.
Common situations: Accidentally passing the private key (which is PEM but not a *public* key parseable here) instead of the public key; exporting the key in the wrong format; copy-paste truncating the PEM armor; key generated with an unsupported curve.
Related errors
- unable to read public key from file
- file contents must be in PEM format
- CA cert for external CA must be in PEM format
- public key file already exists
- provided file is not a supported private key - to add a…
AI-assisted analysis of docker/cli@4f84911bfe (2026-08-07).
Data as JSON: /api/errors/707efe8039c64e3f.
Report an issue: GitHub.
Appendix: source
Thrown at cmd/docker-trust/trust/signer_add.go:134
pubKeys := []data.PublicKey{}
for _, pubKeyPath := range pubKeyPaths {
// Read public key bytes from PEM file, limit to 1 KiB
pubKeyFile, err := os.OpenFile(pubKeyPath, os.O_RDONLY, 0o666)
if err != nil {
return nil, fmt.Errorf("unable to read public key from file: %w", err)
}
defer pubKeyFile.Close()
// limit to
l := io.LimitReader(pubKeyFile, 1<<20)
pubKeyBytes, err := io.ReadAll(l)
if err != nil {
return nil, fmt.Errorf("unable to read public key from file: %w", err)
}
// Parse PEM bytes into type PublicKey
pubKey, err := tufutils.ParsePEMPublicKey(pubKeyBytes)
if err != nil {
return nil, fmt.Errorf("could not parse public key from file: %s: %w", pubKeyPath, err)
}
pubKeys = append(pubKeys, pubKey)
}
return pubKeys, nil
}
View on GitHub (pinned to 4f84911bfe)