oauth2-proxy/oauth2-proxy · error
could not load certificate: %v
Error message
could not load certificate: %v
What it means
Wrap error in setupTLSListener: getCertificate failed while loading the TLS key/cert pair for the HTTPS listener (nil secret source, unreadable file, or X509KeyPair parse failure), so TLS cannot be set up at startup.
Source
Thrown at pkg/proxyhttp/server.go:195
// The HTTPS server can be disabled by setting the SecureBindAddress to "-" or by
// leaving it empty.
func (s *server) setupTLSListener(opts Opts) error {
if opts.SecureBindAddress == "" || opts.SecureBindAddress == "-" {
// No HTTPS listener required
return nil
}
config := &tls.Config{
MinVersion: tls.VersionTLS12, // default, override below
MaxVersion: tls.VersionTLS13,
NextProtos: []string{"http/1.1"},
}
if opts.TLS == nil {
return errors.New("no TLS config provided")
}
cert, err := getCertificate(opts.TLS)
if err != nil {
return fmt.Errorf("could not load certificate: %v", err)
}
config.Certificates = []tls.Certificate{cert}
if len(opts.TLS.CipherSuites) > 0 {
cipherSuites, err := parseCipherSuites(opts.TLS.CipherSuites)
if err != nil {
return fmt.Errorf("could not parse cipher suites: %v", err)
}
config.CipherSuites = cipherSuites
}
if len(opts.TLS.MinVersion) > 0 {
switch opts.TLS.MinVersion {
case "TLS1.2":
config.MinVersion = tls.VersionTLS12
case "TLS1.3":
config.MinVersion = tls.VersionTLS13
default:View on GitHub (pinned to 33c2eb92de)
Solutions
- Read the wrapped error to identify the root cause (file not found, PEM decode failure, key mismatch)
- Verify CertFile and KeyFile paths exist and are readable: test with `openssl x509 -in cert.pem` and `openssl rsa -in key.pem -check`
- Confirm the cert and key belong together by comparing their public key moduli
- If using Secret/mounted secrets, confirm the mount happened and permissions allow the process to read them
Example fix
// before
server, _ := NewServer(ctx, Opts{TLS: &TLS{CertFile: "/etc/ssl/cert.pem", KeyFile: "/etc/ssl/key.pem"}}) // key not mounted
// after
server, _ := NewServer(ctx, Opts{TLS: &TLS{CertFile: "/etc/ssl/tls/tls.crt", KeyFile: "/etc/ssl/tls/tls.key"}}) // verified mount Defensive patterns
Strategy: validation
Validate before calling
// Pre-flight check mirroring getCertificate
if _, err := tls.LoadX509KeyPair("/etc/ssl/tls.crt", "/etc/ssl/tls.key"); err != nil {
return fmt.Errorf("TLS keypair unusable before server start: %w", err)
} Type guard
func certFilesReadable(certFile, keyFile string) bool {
c, err1 := os.ReadFile(certFile)
k, err2 := os.ReadFile(keyFile)
return err1 == nil && err2 == nil &&
bytes.Contains(c, []byte("BEGIN CERTIFICATE")) &&
(bytes.Contains(k, []byte("PRIVATE KEY")))
} Try / catch
srv, err := NewServer(ctx, opts)
if err != nil && strings.Contains(err.Error(), "could not load certificate") {
return fmt.Errorf("check TLS cert/key paths, permissions, and that they form a matching pair: %w", err)
} Prevention
- Verify cert and key load with openssl before every deploy
- Confirm secret mounts land at the exact configured paths
- Keep cert and key versions in sync when rotating certificates
- Ensure the process user can read the private key file
When it happens
Trigger: NewServer → setupTLSListener where opts.TLS is non-nil but getCertificate fails because KeyFile/CertFile do not exist, are unreadable, are not valid PEM, or the key does not match the certificate.
Common situations: Wrong paths in container images (file not copied), expired/reissued certs replaced without updating the key, concatenated files with trailing garbage, running as a user without read permission on the key.
Understand the failure class
Background: "Invalid value" and "allowed values are" config errors: what your library rejected and how to fix it — this error's family across 41 libraries.
- SSL/TLS and certificate errors — how TLS handshakes and certificate validation fail.
Related errors
- error setting up TLS listener: %v
- unknown TLS cipher suite name specified %q
- SystemCertPool is empty
- certificate authority file (%s) could not be read - %s
- loading certificate authority (%s) failed
AI-assisted analysis of oauth2-proxy/oauth2-proxy@33c2eb92de (2026-09-06).
Data as JSON: /api/errors/03da1038f48ad07a.
Report an issue: GitHub.