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

  1. Verify with: base64 -d < cert.b64 | openssl x509 -noout -text (and same for the key)
  2. Re-encode the files: base64 -w0 cert.pem / base64 -w0 key.pem and paste fully
  3. Ensure cert and key values are not swapped and correspond to each other
  4. 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

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

Related errors


AI-assisted analysis of ory/hydra@4174065ffb (2026-09-03). Data as JSON: /api/errors/14d99e14b391f26e. Report an issue: GitHub.