nats-io/nats-server · error

error parsing X509 certificate/key pair %d/%d: %v

Error message

error parsing X509 certificate/key pair %d/%d: %v

What it means

In the multi-certificate path (tc.Certificates list), the server loads each pair with tls.LoadX509KeyPair and wraps failures as 'error parsing X509 certificate/key pair %d/%d: %v', identifying which of N pairs failed (1-based index). The wrapped error contains the actual cause.

Source

Thrown at server/opts.go:5860

			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)
			}
			cert.Leaf, err = x509.ParseCertificate(cert.Certificate[0])
			if err != nil {
				return nil, fmt.Errorf("error parsing certificate %d/%d: %v", i+1, len(tc.Certificates), err)
			}
			config.Certificates[i] = cert
		}
	}

	// Require client certificates as needed
	if tc.Verify {
		config.ClientAuth = tls.RequireAndVerifyClientCert
	}
	// Add in CAs if applicable.
	if tc.CaFile != _EMPTY_ {
		rootPEM, err := os.ReadFile(tc.CaFile)
		if err != nil || rootPEM == nil {
			return nil, err

View on GitHub (pinned to 3a66a489d2)

Solutions

  1. Fix the failing pair indicated by the first number (i+1) in the message — check file existence, PEM validity, and cert/key matching for that entry
  2. Validate all pairs offline with tls.LoadX509KeyPair in a small test program before restart
  3. Remove stale entries from the certificate list
Defensive patterns

Strategy: validation

Validate before calling

for i, p := range cfg.TLS.Certificates {
  if _, err := tls.LoadX509KeyPair(p.CertFile, p.KeyFile); err != nil {
    return fmt.Errorf("pair %d/%d invalid: %w", i+1, len(cfg.TLS.Certificates), err)
  }
}

Try / catch

if err := preflightAllPairs(cfg.TLS.Certificates); err != nil {
  log.Fatalf("multi-cert config invalid: %v", err)
}

Prevention

When it happens

Trigger: Providing multiple certificate pairs via the Certificates option where any one pair fails to load — unreadable files, mismatched cert/key, invalid PEM.

Common situations: Rotating certificates where one of several SNI pairs was updated incompletely; duplicated config entries pointing at removed files.

Understand the failure class

Related errors


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