ory/hydra · critical
unable to load TLS certificate for interface %s: %w
Error message
unable to load TLS certificate for interface %s: %w
What it means
configx TLS.GetCertFunc wraps tlsx.CertificateFromBase64 failures with "unable to load TLS certificate for interface %s: %w". When both cert and key are supplied as base64 strings, they are decoded and parsed into an x509 certificate; any decode/parse failure is reported against the named interface.
Source
Thrown at oryx/configx/serve.go:111
func (p *Provider) TLS(prefix string, defaults TLS) TLS {
prefix = cleanPrefix(prefix)
return TLS{
Enabled: p.BoolF(prefix+"enabled", defaults.Enabled),
AllowTerminationFrom: p.StringsF(prefix+"allow_termination_from", defaults.AllowTerminationFrom),
CertBase64: p.StringF(prefix+"cert.base64", defaults.CertBase64),
KeyBase64: p.StringF(prefix+"key.base64", defaults.KeyBase64),
CertPath: p.StringF(prefix+"cert.path", defaults.CertPath),
KeyPath: p.StringF(prefix+"key.path", defaults.KeyPath),
}
}
func (t *TLS) GetCertFunc(ctx context.Context, l *logrusx.Logger, ifaceName string) (tlsx.CertFunc, error) {
switch {
case t.CertBase64 != "" && t.KeyBase64 != "":
cert, err := tlsx.CertificateFromBase64(t.CertBase64, t.KeyBase64)
if err != nil {
return nil, fmt.Errorf("unable to load TLS certificate for interface %s: %w", ifaceName, err)
}
l.Infof("Setting up HTTPS for %s", ifaceName)
return func(*tls.ClientHelloInfo) (*tls.Certificate, error) { return &cert, nil }, nil
case t.CertPath != "" && t.KeyPath != "":
errs := make(chan error, 1)
getCert, err := tlsx.GetCertificate(ctx, t.CertPath, t.KeyPath, errs)
if err != nil {
return nil, fmt.Errorf("unable to load TLS certificate for interface %s: %w", ifaceName, err)
}
go func() {
for {
select {
case <-ctx.Done():
return
case err := <-errs:
l.WithError(err).Error("Failed to reload TLS certificates, using previous certificates")
}
}View on GitHub (pinned to 4174065ffb)
Solutions
- Verify with: base64 -d < cert.b64 | openssl x509 -noout -text (and same for the key)
- Re-encode the files: base64 -w0 cert.pem / base64 -w0 key.pem and paste fully
- Ensure cert and key values are not swapped and correspond to each other
- Regenerate the certificate if it fails parsing/expired
Example fix
# before tls: cert_base64: <truncated> # after tls: cert_base64: $(base64 -w0 cert.pem) key_base64: $(base64 -w0 key.pem)
Defensive patterns
Strategy: validation
Validate before calling
if _, err := base64.StdEncoding.DecodeString(certB64); err != nil {
return fmt.Errorf("invalid base64: %w", err)
} Try / catch
if err != nil {
log.Fatalf("base64 TLS cert invalid: %v", err)
} Prevention
- Use base64 -w0 for encoding
- Round-trip decode to verify before deploy
- Keep cert/key pairs together and labeled
When it happens
Trigger: Configuring serve tls cert/key base64 values where the base64 is invalid, decodes to a malformed PEM, the cert is expired, or the key does not match the certificate.
Common situations: Base64-encoding the PEM file including newlines incorrectly, swapping cert and key values, truncating the base64 in YAML, using an ECDSA key path unsupported by the parser.
Understand the failure class
- SSL/TLS and certificate errors — how TLS handshakes and certificate validation fail.
Related errors
- unable to base64 decode the TLS certificate: %v
- unable to base64 decode the TLS private key: %v
- no tls configuration was found
- tls configuration is invalid
- issuer URL scheme must be HTTPS unless development mode is e
AI-assisted analysis of ory/hydra@4174065ffb (2026-09-03).
Data as JSON: /api/errors/14d99e14b391f26e.
Report an issue: GitHub.