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

  1. Verify both cert_file and key_file paths exist and are readable by the Nomad agent user
  2. Confirm cert and key are a matching pair: openssl x509 -noout -modulus -in cert.crt vs openssl rsa -noout -modulus -in key.key
  3. 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

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


AI-assisted analysis of hashicorp/nomad@482b49bf1a (2026-09-04). Data as JSON: /api/errors/0b4d127ff34f20ae. Report an issue: GitHub.