gofiber/fiber · critical
tls: cannot load TLS key pair from certFile=
Error message
tls: cannot load TLS key pair from certFile=%q and keyFile=%q: %w
What it means
Returned by App.Listen / ListenTLS at startup when tls.LoadX509KeyPair fails to load the configured CertFile and CertKeyFile. The error wraps the cert and key paths and the underlying crypto/tls error: 'tls: cannot load TLS key pair from certFile="server.crt" and keyFile="server.key": open server.crt: no such file or directory'. Fires only when both CertFile and CertKeyFile are set and TLSConfig is nil (the manual-cert branch at listen.go:227).
Solutions
- Verify both files exist and are readable by the process uid; log their absolute paths at startup.
- Confirm the key file is PEM-encoded (BEGIN PRIVATE KEY / BEGIN RSA PRIVATE KEY / BEGIN EC PRIVATE KEY) and matches the cert's public key.
- Use absolute paths or resolve them from a known root; in containers, mount certs from a secret and reference the mount path.
- Validate the pair in isolation with tls.LoadX509KeyPair in a tiny program or a startup self-check before Listen.
Example fix
// before
app.ListenTLS(":443", "server.crt", "server.key") // paths wrong / unreadable
// after
if _, err := tls.LoadX509KeyPair(certPath, keyPath); err != nil {
log.Fatalf("cert check failed: %v", err)
}
app.ListenTLS(":443", certPath, keyPath) Defensive patterns
Strategy: validation
Validate before calling
// preflight: load and validate the cert/key pair before Listen
if _, err := tls.LoadX509KeyPair(certFile, keyFile); err != nil {
log.Fatalf("invalid TLS key pair: %v", err)
}
if _, err := os.Stat(certFile); err != nil { log.Fatal(err) }
if _, err := os.Stat(keyFile); err != nil { log.Fatal(err) } Type guard
null
Try / catch
if err := app.ListenTLS(":443", certFile, keyFile); err != nil {
if strings.Contains(err.Error(), "cannot load TLS key pair") {
log.Fatalf("TLS cert/key invalid: %v", err)
}
log.Fatal(err)
} Prevention
- Self-check tls.LoadX509KeyPair at startup before calling ListenTLS.
- Use absolute paths or resolve from a known root; mount secrets in containers.
- Confirm the key file is PEM and its type matches the cert (RSA/EC/private key).
- Do not mix AutoCertManager with manual CertFile/CertKeyFile (that returns ErrAutoCertWithCertFile instead).
When it happens
Trigger: Calling app.ListenTLS(...) or app.Listen(addr, WithTLS(cert, key)) where the cert or key file cannot be read or is not a valid PEM-encoded X.509 key pair. AutoCertManager being set with cert files returns a different error (ErrAutoCertWithCertFile) earlier.
Common situations: Wrong paths (relative path resolved against cwd, not source), cert/key not mounted into the container, permissions on the key file, PEM block missing or wrong type (e.g. cert file contains only the chain without the leaf, key file is PKCS#12 instead of PEM), expired/rotated cert files replaced incompletely, or cert and key swapped.
Understand the failure class
- SSL/TLS and certificate errors — how TLS handshakes and certificate validation fail.
Related errors
- failed to listen
- unsupported TLS version, please use tls.VersionTLS12 or…
- client: HTTPS to HTTP redirect blocked
- [CORS] Configuration error: When 'AllowCredentials' is set…
- [CORS] Invalid origin format in configuration:
AI-assisted analysis of gofiber/fiber@a105acad6c (2026-08-11).
Data as JSON: /api/errors/4a30b810daaf678e.
Report an issue: GitHub.
Appendix: source
Thrown at listen.go:230
func (app *App) Listen(addr string, config ...ListenConfig) error {
cfg := listenConfigDefault(config...)
// Configure TLS
var tlsConfig *tls.Config
var tlsHandler *TLSHandler
if cfg.TLSConfig != nil {
tlsConfig = cfg.TLSConfig.Clone()
warnSupersededTLSFields(&cfg)
} else {
validateTLSMinVersion(&cfg)
switch {
case cfg.AutoCertManager != nil && (cfg.CertFile != "" || cfg.CertKeyFile != ""):
return ErrAutoCertWithCertFile
case cfg.CertFile != "" && cfg.CertKeyFile != "":
cert, err := tls.LoadX509KeyPair(cfg.CertFile, cfg.CertKeyFile)
if err != nil {
return fmt.Errorf("tls: cannot load TLS key pair from certFile=%q and keyFile=%q: %w", cfg.CertFile, cfg.CertKeyFile, err)
}
tlsHandler = &TLSHandler{}
tlsConfig = &tls.Config{
MinVersion: cfg.TLSMinVersion,
Certificates: []tls.Certificate{
cert,
},
GetCertificate: tlsHandler.GetClientInfo,
}
case cfg.AutoCertManager != nil:
tlsConfig = &tls.Config{
MinVersion: cfg.TLSMinVersion,
GetCertificate: cfg.AutoCertManager.GetCertificate,
NextProtos: []string{"http/1.1", "acme-tls/1"},
}
default:View on GitHub (pinned to a105acad6c)