golang/go · error

tls: no certificates configured

Error message

tls: no certificates configured

What it means

errNoCertificates is the sentinel returned when a TLS server has no certificate to present. It is a package-level errors.New value (linknamed by external packages) thrown from Config.getCertificate when no Certificates and no GetCertificate callback yields a cert. Without a certificate the server cannot authenticate.

Source

Thrown at src/crypto/tls/common.go:1331

	supportedVersions := c.supportedVersions(isClient, isQUIC)
	for _, v := range supportedVersions {
		if slices.Contains(peerVersions, v) {
			return v, true
		}
	}
	return 0, false
}

// errNoCertificates should be an internal detail,
// but widely used packages access it using linkname.
// Notable members of the hall of shame include:
//   - github.com/xtls/xray-core
//
// Do not remove or change the type signature.
// See go.dev/issue/67401.
//
//go:linkname errNoCertificates
var errNoCertificates = errors.New("tls: no certificates configured")

// getCertificate returns the best certificate for the given ClientHelloInfo,
// defaulting to the first element of c.Certificates.
func (c *Config) getCertificate(clientHello *ClientHelloInfo) (*Certificate, error) {
	if c.GetCertificate != nil &&
		(len(c.Certificates) == 0 || len(clientHello.ServerName) > 0) {
		cert, err := c.GetCertificate(clientHello)
		if cert != nil || err != nil {
			return cert, err
		}
	}

	if len(c.Certificates) == 0 {
		return nil, errNoCertificates
	}

	if len(c.Certificates) == 1 {
		// There's only one choice, so no point doing any work.

View on GitHub (pinned to b6b368adc5)

Solutions

  1. Load a key pair into Config.Certificates with tls.LoadX509KeyPair(certFile, keyFile).
  2. Implement Config.GetCertificate to return a cert (e.g., via certmagic/autocert) for the requested SNI.
  3. Fail fast at startup: assert len(cfg.Certificates) > 0 or GetCertificate != nil before listening.
  4. Check that LoadX509KeyPair errors are not ignored during config setup.

Example fix

// before
cfg := &tls.Config{} // empty
go http.ListenAndServeTLS(":443", "", "", nil) // wrong: no cert files

// after
cert, err := tls.LoadX509KeyPair("cert.pem", "key.pem")
if err != nil { return err }
cfg := &tls.Config{Certificates: []tls.Certificate{cert}}
srv := &http.Server{Addr: ":443", TLSConfig: cfg}
return srv.ListenAndServeTLS("", "")
Defensive patterns

Strategy: validation

Validate before calling

// Fail fast at startup if the server has no certificate to serve.
func mustHaveCert(cfg *tls.Config) error {
    if cfg == nil { return errors.New("tls config is nil") }
    if len(cfg.Certificates) == 0 && cfg.GetCertificate == nil {
        return errors.New("tls: no certificates configured (load a key pair or set GetCertificate)")
    }
    return nil
}

Prevention

When it happens

Trigger: A tls.Listener or http.Server with TLSConfig that has an empty Certificates slice and no GetCertificate/GetConfigForClient callback, receiving a ClientHello that names no SNI the server can map to a cert.

Common situations: Forgot to load tls.LoadX509KeyPair into Config.Certificates; config built from a template that dropped the cert field; SNI-based routing where the requested name has no matching cert; cert loaded from a path that failed silently.

Understand the failure class

Related errors


AI-assisted analysis of golang/go@b6b368adc5 (2026-08-12). Data as JSON: /api/errors/8ff8e6f34f63d48d. Report an issue: GitHub.