nats-io/nats-server · error

error parsing X509 certificate/key pair: %v

Error message

error parsing X509 certificate/key pair: %v

What it means

tls.LoadX509KeyPair failed while loading the configured cert_file/key_file, and the server wraps the underlying error with this message. The files may be unreadable, malformed PEM, or mismatched cert/key.

Source

Thrown at server/opts.go:5842

	config := tls.Config{
		MinVersion:         tls.VersionTLS12,
		CipherSuites:       tc.Ciphers,
		CurvePreferences:   tc.CurvePreferences,
		InsecureSkipVerify: tc.Insecure,
	}

	switch {
	case tc.CertFile != _EMPTY_ && tc.CertStore != certstore.STOREEMPTY:
		return nil, certstore.ErrConflictCertFileAndStore
	case tc.CertFile != _EMPTY_ && tc.KeyFile == _EMPTY_:
		return nil, fmt.Errorf("missing 'key_file' in TLS configuration")
	case tc.CertFile == _EMPTY_ && tc.KeyFile != _EMPTY_:
		return nil, fmt.Errorf("missing 'cert_file' in TLS configuration")
	case tc.CertFile != _EMPTY_ && tc.KeyFile != _EMPTY_:
		// Now load in cert and private key
		cert, err := tls.LoadX509KeyPair(tc.CertFile, tc.KeyFile)
		if err != nil {
			return nil, fmt.Errorf("error parsing X509 certificate/key pair: %v", err)
		}
		cert.Leaf, err = x509.ParseCertificate(cert.Certificate[0])
		if err != nil {
			return nil, fmt.Errorf("error parsing certificate: %v", err)
		}
		config.Certificates = []tls.Certificate{cert}
	case tc.CertStore != certstore.STOREEMPTY:
		err := certstore.TLSConfig(tc.CertStore, tc.CertMatchBy, tc.CertMatch, tc.CaCertsMatch, tc.CertMatchSkipInvalid, &config)
		if err != nil {
			return nil, err
		}
	case tc.Certificates != nil:
		// Multiple certificate support.
		config.Certificates = make([]tls.Certificate, len(tc.Certificates))
		for i, certPair := range tc.Certificates {
			cert, err := tls.LoadX509KeyPair(certPair.CertFile, certPair.KeyFile)
			if err != nil {
				return nil, fmt.Errorf("error parsing X509 certificate/key pair %d/%d: %v", i+1, len(tc.Certificates), err)

View on GitHub (pinned to 3a66a489d2)

Solutions

  1. Verify both files exist, are valid PEM, and readable by the server user (the wrapped %v names the underlying cause)
  2. Check that cert and key form a matching pair (compare public key / modulus)
  3. Decrypt or remove passphrase from the key file
  4. Re-export the certificate chain including intermediates
Defensive patterns

Strategy: validation

Validate before calling

if _, err := tls.LoadX509KeyPair(cfg.TLS.CertFile, cfg.TLS.KeyFile); err != nil {
  return fmt.Errorf("pre-flight keypair check failed: %w", err)
}

Try / catch

if _, err := tls.LoadX509KeyPair(cert, key); err != nil {
  return fmt.Errorf("invalid cert/key pair %s/%s: %w", cert, key, err)
}

Prevention

When it happens

Trigger: parseTLS calling tls.LoadX509KeyPair(tc.CertFile, tc.KeyFile) which returns a non-nil error (bad permissions, invalid PEM blocks, encrypted keys, mismatched pair).

Common situations: Wrong file permissions; concatenating cert and key into wrong files; key encrypted with a passphrase; files truncated by failed deployments.

Understand the failure class

Related errors


AI-assisted analysis of nats-io/nats-server@3a66a489d2 (2026-09-02). Data as JSON: /api/errors/94f7158014b7aab1. Report an issue: GitHub.