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
- Load a key pair into Config.Certificates with tls.LoadX509KeyPair(certFile, keyFile).
- Implement Config.GetCertificate to return a cert (e.g., via certmagic/autocert) for the requested SNI.
- Fail fast at startup: assert len(cfg.Certificates) > 0 or GetCertificate != nil before listening.
- 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
- Always check the error from tls.LoadX509KeyPair before adding to Certificates.
- Assert non-empty Certificates (or GetCertificate) at program start.
- For SNI routing, implement GetCertificate and return an error only for truly unknown names.
- Add a startup smoke test that opens the TLS listener with the real config.
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
- SSL/TLS and certificate errors — how TLS handshakes and certificate validation fail.
Related errors
- ECDSA verification failure
- Ed25519 verification failure
- tls: missing signature_algorithms from TLS 1.2 peer
- tls: peer doesn't support any of the certificate's signature
- tls: ML-DSA certificates require TLS 1.3
AI-assisted analysis of golang/go@b6b368adc5 (2026-08-12).
Data as JSON: /api/errors/8ff8e6f34f63d48d.
Report an issue: GitHub.