hashicorp/nomad · error
Failed to load cert/key pair: %v
Error message
Failed to load cert/key pair: %v
What it means
TLSConfig.LoadKeyPair lazily loads the certificate and key from disk with tls.LoadX509KeyPair. If the files cannot be read, are missing, or the cert/key do not match, the underlying error is wrapped as 'Failed to load cert/key pair'.
Source
Thrown at nomad/structs/config/tls.go:94
cacheLock sync.Mutex
certificate *tls.Certificate
}
// LoadKeyPair reloads the TLS certificate based on the specified certificate
// and key file. If successful, stores the certificate for further use.
func (k *KeyLoader) LoadKeyPair(certFile, keyFile string) (*tls.Certificate, error) {
k.cacheLock.Lock()
defer k.cacheLock.Unlock()
// Allow downgrading
if certFile == "" && keyFile == "" {
k.certificate = nil
return nil, nil
}
cert, err := tls.LoadX509KeyPair(certFile, keyFile)
if err != nil {
return nil, fmt.Errorf("Failed to load cert/key pair: %v", err)
}
k.certificate = &cert
return k.certificate, nil
}
func (k *KeyLoader) GetCertificate() *tls.Certificate {
k.cacheLock.Lock()
defer k.cacheLock.Unlock()
return k.certificate
}
// GetOutgoingCertificate fetches the currently-loaded certificate when
// accepting a TLS connection. This currently does not consider information in
// the ClientHello and only returns the certificate that was last loaded.
func (k *KeyLoader) GetOutgoingCertificate(*tls.ClientHelloInfo) (*tls.Certificate, error) {
k.cacheLock.Lock()
defer k.cacheLock.Unlock()View on GitHub (pinned to 482b49bf1a)
Solutions
- Verify both cert_file and key_file paths exist and are readable by the Nomad agent user
- Confirm cert and key are a matching pair: openssl x509 -noout -modulus -in cert.crt vs openssl rsa -noout -modulus -in key.key
- Regenerate/re-export the PEM files if they are corrupt or in a non-PEM format
Example fix
// before
tls {
cert_file = "/etc/nomad/server.crt"
key_file = "/etc/nomad/old-server.key"
}
// after
tls {
cert_file = "/etc/nomad/server.crt"
key_file = "/etc/nomad/server.key"
} Defensive patterns
Strategy: validation
Validate before calling
if _, err := tls.LoadX509KeyPair(cfg.TLS.CertFile, cfg.TLS.KeyFile); err != nil {
return fmt.Errorf("preflight cert/key check failed: %w", err)
} Try / catch
cert, err := tlsCfg.LoadKeyPair()
if err != nil {
return fmt.Errorf("tls setup failed: %w (verify cert_file/key_file paths, permissions, and pair match)", err)
} Prevention
- Deploy cert and key files together so they always match
- Check file readability as the agent's service user
- Run openssl x509/openssl rsa modulus comparison before rollout
- Preflight-load the pair at config-load time, not first use
When it happens
Trigger: First call that needs the certificate (after the pair was configured) invokes LoadKeyPair and crypto/tls fails to read/parse certFile+keyFile, e.g. nonexistent path, bad PEM, or mismatched pair.
Common situations: Wrong paths after moving configs between hosts; cert renewed but key not updated (mismatch); unreadable file permissions; corrupt or truncated PEM files.
Related errors
- failed to set up TLS expiration metrics: %w
- failed to initialize HTTP server TLS configuration: %s
- plugin not found
- wait config is nil or empty
- wait config is empty
AI-assisted analysis of hashicorp/nomad@482b49bf1a (2026-09-04).
Data as JSON: /api/errors/0b4d127ff34f20ae.
Report an issue: GitHub.