ory/hydra · error

failed to encode private key: %s

Error message

failed to encode private key: %s

What it means

After successfully creating the DER-encoded certificate, CreateSelfSignedCertificate parses it back with x509.ParseCertificate to return an *x509.Certificate. If that parse fails, it returns this error (whose wording — 'failed to encode private key' — is misleading; it actually means the freshly generated certificate could not be parsed). In practice this is nearly impossible unless the crypto/x509 implementation is broken or a CertificateOpts produced a malformed template.

Source

Thrown at oryx/tlsx/cert.go:284

		NotAfter:              time.Now().UTC().Add(time.Hour * 24 * 31),
		KeyUsage:              x509.KeyUsageKeyEncipherment | x509.KeyUsageDigitalSignature | x509.KeyUsageCertSign,
		ExtKeyUsage:           []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth, x509.ExtKeyUsageClientAuth},
		BasicConstraintsValid: true,
		IsCA:                  true,
		DNSNames:              []string{"localhost"},
	}
	for _, opt := range opts {
		opt(certificate)
	}

	der, err := x509.CreateCertificate(rand.Reader, certificate, certificate, PublicKey(key), key)
	if err != nil {
		return cert, errors.Errorf("failed to create certificate: %s", err)
	}

	cert, err = x509.ParseCertificate(der)
	if err != nil {
		return cert, errors.Errorf("failed to encode private key: %s", err)
	}
	return cert, nil
}

// PEMBlockForKey returns a PEM-encoded block for key.
func PEMBlockForKey(key interface{}) (*pem.Block, error) {
	b, err := x509.MarshalPKCS8PrivateKey(key)
	if err != nil {
		return nil, errors.WithStack(err)
	}
	return &pem.Block{Type: "PRIVATE KEY", Bytes: b}, nil
}

// NewClientCert creates a new client TLS certificate signed by the given CA.
func NewClientCert(CAcert *x509.Certificate, CAkey crypto.PrivateKey, opts ...CertificateOpts) (*tls.Certificate, error) {
	if !slices.Contains(CAcert.ExtKeyUsage, x509.ExtKeyUsageClientAuth) {
		return nil, errors.Errorf("the CA certificate does not have the client authentication extended key usage (OID 1.3.6.1.5.5.7.3.2) set")
	}

View on GitHub (pinned to 4174065ffb)

Solutions

  1. Review any custom CertificateOpts functions for values that produce invalid certificate fields (e.g. bad extensions, invalid validity ranges).
  2. Retry the generation — transient crypto-stack failures resolve on re-run.
  3. Update the Go toolchain/runtime to a current patch version to rule out a crypto/x509 bug.

Example fix

// before
opt(certificate) // sets NotBefore after NotAfter
// after
opt(certificate) // ensure opts keep NotBefore < NotAfter and valid fields
Defensive patterns

Strategy: try-catch

Validate before calling

// Verify custom opts keep fields valid:
// c.NotBefore.Before(c.NotAfter), no duplicate extensions, valid DNS names.

Try / catch

cert, err := tlsx.CreateSelfSignedCertificate(key, opts...)
if err != nil && strings.Contains(err.Error(), "failed to encode private key") {
    // misleading message: DER parse failed — audit opts, then retry once
}

Prevention

When it happens

Trigger: x509.ParseCertificate rejecting the DER bytes returned by x509.CreateCertificate — essentially only possible with a corrupted crypto stack or an exotic opts callback that produced an invalid certificate structure.

Common situations: Extremely rare; occasionally seen on platforms with patched/broken crypto libraries, or when a custom CertificateOpts injects invalid extensions the parser then rejects.

Related errors


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