nsqio/nsq · error
failed to LoadX509KeyPair %s, %s - %s
Error message
failed to LoadX509KeyPair %s, %s - %s
What it means
During nsqadmin startup (New in nsqadmin/nsqadmin.go), when both --http-client-tls-cert and --http-client-tls-key are set, tls.LoadX509KeyPair parses both PEM files to build the client certificate nsqadmin will present to nsqd/nsqlookupd HTTPS endpoints. Any parse failure — unreadable file, missing PRIVATE KEY block, cert/key mismatch, or encrypted key needing a passphrase (not supported here) — returns 'failed to LoadX509KeyPair %s, %s - %s' naming both paths and the crypto/tls cause, and nsqadmin exits.
Source
Thrown at nsqadmin/nsqadmin.go:66
if len(opts.NSQDHTTPAddresses) != 0 && len(opts.NSQLookupdHTTPAddresses) != 0 {
return nil, errors.New("use --nsqd-http-address or --lookupd-http-address not both")
}
if opts.HTTPClientTLSCert != "" && opts.HTTPClientTLSKey == "" {
return nil, errors.New("--http-client-tls-key must be specified with --http-client-tls-cert")
}
if opts.HTTPClientTLSKey != "" && opts.HTTPClientTLSCert == "" {
return nil, errors.New("--http-client-tls-cert must be specified with --http-client-tls-key")
}
n.httpClientTLSConfig = &tls.Config{
InsecureSkipVerify: opts.HTTPClientTLSInsecureSkipVerify,
}
if opts.HTTPClientTLSCert != "" && opts.HTTPClientTLSKey != "" {
cert, err := tls.LoadX509KeyPair(opts.HTTPClientTLSCert, opts.HTTPClientTLSKey)
if err != nil {
return nil, fmt.Errorf("failed to LoadX509KeyPair %s, %s - %s",
opts.HTTPClientTLSCert, opts.HTTPClientTLSKey, err)
}
n.httpClientTLSConfig.Certificates = []tls.Certificate{cert}
}
if opts.HTTPClientTLSRootCAFile != "" {
tlsCertPool := x509.NewCertPool()
caCertFile, err := os.ReadFile(opts.HTTPClientTLSRootCAFile)
if err != nil {
return nil, fmt.Errorf("failed to read TLS root CA file %s - %s",
opts.HTTPClientTLSRootCAFile, err)
}
if !tlsCertPool.AppendCertsFromPEM(caCertFile) {
return nil, fmt.Errorf("failed to AppendCertsFromPEM %s", opts.HTTPClientTLSRootCAFile)
}
n.httpClientTLSConfig.RootCAs = tlsCertPool
}
for _, address := range opts.NSQLookupdHTTPAddresses {View on GitHub (pinned to 85cf10c09c)
Solutions
- Validate the pair exactly as Go will: 'openssl x509 -in cert.pem -noout -modulus | openssl md5' and 'openssl rsa -in key.pem -noout -modulus | openssl md5' — the hashes must match.
- If the key is encrypted, decrypt it first: 'openssl rsa -in key.enc -out key.pem' (this code path supports no passphrase).
- Confirm both files are PEM with proper BEGIN/END blocks and were mounted/rotated together.
- Restart nsqadmin after fixing; it should reach 'listening on'.
Example fix
# before nsqadmin --http-client-tls-cert=client.crt --http-client-tls-key=client.key # failed to LoadX509KeyPair client.crt, client.key - tls: private key does not match public key # after openssl x509 -in client.crt -noout -modulus | openssl md5 openssl rsa -in client.key -noout -modulus | openssl md5 # re-export a matching pair from your CA, then rerun nsqadmin
Defensive patterns
Strategy: validation
Validate before calling
// pre-start: load the exact pair exactly the way nsqadmin will
if opts.HTTPClientTLSCert != "" || opts.HTTPClientTLSKey != "" {
if opts.HTTPClientTLSCert == "" || opts.HTTPClientTLSKey == "" {
return errors.New("cert and key must be set together")
}
if _, err := tls.LoadX509KeyPair(opts.HTTPClientTLSCert, opts.HTTPClientTLSKey); err != nil {
return fmt.Errorf("bad client cert pair: %w", err)
}
} Try / catch
// deployment scripts: detect the class of failure from the message
if err := startNsqadmin(cfg); err != nil && strings.Contains(err.Error(), "failed to LoadX509KeyPair") {
return errors.New("nsqadmin client cert/key invalid: verify PEM pair match and no passphrase")
} Prevention
- Provision cert and key as one atomic unit (same secret, same rotation).
- Use unencrypted PEM keys for nsqadmin client certs.
- Run an openssl modulus comparison in CI for every rotated pair.
When it happens
Trigger: Configuring nsqadmin with a cert file that is not PEM, a key file that is actually the certificate or a CSR, a key generated for a different certificate, or a passphrase-protected key (LoadX509KeyPair in this call passes no password), or a truncated/empty file from a failed secret mount.
Common situations: Secrets mounted wrong in k8s (empty dir instead of secret), vault templating emitting placeholders, copying the server's cert but forgetting its key, certs rotated on one path only, ops passing the CA instead of the leaf.
Related errors
- failed to AppendCertsFromPEM %s
- failed to append certificate to pool
- failed to read TLS root CA file %s - %s
- unknown tlsVersionOption %q
- failed to resolve --lookupd-http-address (%s) - %s
AI-assisted analysis of nsqio/nsq@85cf10c09c (2026-08-16).
Data as JSON: /api/errors/3e8092699993f80e.
Report an issue: GitHub.