hashicorp/nomad · error
Failed to load cert/key pair
Error message
Failed to load cert/key pair: %v
What it means
LoadKeyPair delegates to Config.KeyLoader.LoadKeyPair(CertFile, KeyFile) to read and parse the certificate/private-key pair into a tls.Certificate. Any failure from the loader (unreadable file, PEM parse error, mismatched key, encrypted key) is wrapped in this error. It means TLS identity files could not be loaded.
Solutions
- Read the wrapped %v cause and fix that specific problem (path, permission, or parse error).
- Verify the pair matches: compare modulus/public keys (openssl x509 -noout -modulus vs openssl rsa -noout -modulus).
- Validate files with openssl x509 / openssl pkey; re-export the key in an unencrypted PKCS#8/PEM format Go supports.
- Ensure CertFile holds the leaf cert (chain first) and KeyFile the corresponding private key, both readable by the process.
Example fix
// before cfg.KeyFile = "old-key.pem" // key regenerated, no longer matches cert // after cfg.CertFile = "new-cert.pem" cfg.KeyFile = "new-key.pem" // matching pair from the same issuance
Defensive patterns
Strategy: validation
Validate before calling
func validateKeyPair(certPath, keyPath string) error {
certPEM, err := os.ReadFile(certPath); if err != nil { return err }
keyPEM, err := os.ReadFile(keyPath); if err != nil { return err }
cert, err := tls.X509KeyPair(certPEM, keyPEM)
if err != nil { return fmt.Errorf("cert/key mismatch or unparsable: %w", err) }
leaf, err := x509.ParseCertificate(cert.Certificate[0])
if err != nil { return err }
if time.Now().After(leaf.NotAfter) { return fmt.Errorf("certificate expired %s", leaf.NotAfter) }
return nil
} Try / catch
cert, err := cfg.LoadKeyPair()
if err != nil && strings.Contains(err.Error(), "Failed to load cert/key pair") {
if verr := validateKeyPair(cfg.CertFile, cfg.KeyFile); verr != nil {
return fmt.Errorf("TLS identity files invalid: %w", verr)
}
return err
} Prevention
- Validate cert/key pairs with tls.X509KeyPair (or openssl) before deployment and after each rotation.
- Always rotate cert and key together from the same issuance.
- Ensure both files are readable by the service user and use unencrypted, Go-supported key formats (PKCS#8/PEM).
- Monitor certificate expiry and rotate before NotAfter.
When it happens
Trigger: CertFile and KeyFile are set and a KeyLoader exists, but loading fails — missing/unreadable files, invalid PEM, certificate and key not matching, unsupported key format (e.g. encrypted PKCS#8 without password), or expired/invalid cert bytes.
Common situations: Wrong key paired with the cert after rotation; cert file actually containing a chain without the key or vice versa; permissions blocking the process user; keys generated with algorithms/options the Go TLS stack cannot parse.
Related errors
- Failed to parse any valid certificates in CA file
- Failed to read CA file
- cannot reload agent with nil configuration
- failed to configure TLS
- failed to initialize Consul client config
AI-assisted analysis of hashicorp/nomad@482b49bf1a (2026-09-04).
Data as JSON: /api/errors/0195a9571d47a5ee.
Report an issue: GitHub.
Appendix: source
Thrown at helper/tlsutil/config.go:209
return fmt.Errorf("Failed to parse any valid certificates in CA file: %s", c.CAFile)
}
return nil
}
// LoadKeyPair is used to open and parse a certificate and key file
func (c *Config) LoadKeyPair() (*tls.Certificate, error) {
if c.CertFile == "" || c.KeyFile == "" {
return nil, nil
}
if c.KeyLoader == nil {
return nil, fmt.Errorf("No Keyloader object to perform LoadKeyPair")
}
cert, err := c.KeyLoader.LoadKeyPair(c.CertFile, c.KeyFile)
if err != nil {
return nil, fmt.Errorf("Failed to load cert/key pair: %v", err)
}
return cert, err
}
// OutgoingTLSConfig generates a TLS configuration for outgoing
// requests. It will return a nil config if this configuration should
// not use TLS for outgoing connections. Provides a callback to
// fetch certificates, allowing for reloading on the fly.
func (c *Config) OutgoingTLSConfig() (*tls.Config, error) {
// If VerifyServerHostname is true, that implies VerifyOutgoing
if c.VerifyServerHostname {
c.VerifyOutgoing = true
}
if !c.VerifyOutgoing {
return nil, nil
}
// Create the tlsConfig
tlsConfig := &tls.Config{View on GitHub (pinned to 482b49bf1a)