siyuan-note/siyuan · critical

failed to generate TLS server certificate: %w

Error message

failed to generate TLS server certificate: %w

What it means

refreshCertificate issues a fresh server leaf certificate with createServerCertificate, signing it with the loaded CA. If X.509 template construction or signing fails (invalid SAN input, unsupported key algorithm, signing errors), the failure is wrapped as this error and the TLS handshake cannot proceed.

Source

Thrown at kernel/util/tls_cert_manager.go:160

		(localIP == nil || certificateContainsIP(currentState.leaf, localIP)) {
		return &currentState.certificate, nil
	}

	privateKey, ok := currentState.certificate.PrivateKey.(crypto.Signer)
	if !ok {
		return nil, fmt.Errorf("TLS server private key does not implement crypto.Signer")
	}

	caCert, caKey, err := loadCA(manager.caCertPath, manager.caKeyPath)
	if err != nil {
		return nil, fmt.Errorf("failed to load CA certificates: %w", err)
	}

	ipAddresses := collectServerCertificateIPs(currentState.leaf.IPAddresses, localIP)
	dnsNames := collectServerCertificateDNSNames(currentState.leaf.DNSNames)
	certDER, leaf, err := createServerCertificate(caCert, caKey, privateKey, ipAddresses, dnsNames)
	if err != nil {
		return nil, fmt.Errorf("failed to generate TLS server certificate: %w", err)
	}

	certificate := tls.Certificate{
		Certificate: [][]byte{certDER},
		PrivateKey:  privateKey,
		Leaf:        leaf,
	}
	newState := &tlsCertificateState{certificate: certificate, leaf: leaf}
	manager.state.Store(newState)

	certPEM := pem.EncodeToMemory(&pem.Block{Type: "CERTIFICATE", Bytes: certDER})
	if err = gulu.File.WriteFileSafer(manager.certPath, certPEM, 0644); err != nil {
		logging.LogWarnf("failed to persist refreshed TLS server certificate: %s", err)
	}

	if localIP == nil {
		logging.LogInfof("refreshed TLS server certificate before expiration")
	} else {

View on GitHub (pinned to 8641553a1f)

Solutions

  1. Inspect the wrapped cause; fix SAN inputs (ensure the CA-derived leaf has at least one valid IP/DNS SAN)
  2. Correct the system clock/timezone if the validity period was out of range
  3. Regenerate the CA pair (delete CA files and restart) if the CA key is unusable for signing
  4. Ensure crypto.Signer keys are supported (RSA/ECDSA) by the CA

Example fix

// before: system clock set to 1970 -> createServerCertificate: validity out of range
// after: sync system time, then
state, err := currentState.refreshCertificate(localIP) // succeeds
Defensive patterns

Strategy: try-catch

Validate before calling

// verify system clock sanity before issuing certs
if skew := time.Since(time.Now().UTC()).Abs(); skew > time.Hour {
	// system clock unreliable: certificate validity windows will be wrong
}

Try / catch

cert, err := certManager.GetCertificate(hello)
if err != nil {
	logging.LogErrorf("certificate refresh failed: %s", err)
	return nil, err // fail the handshake rather than serving a stale cert
}

Prevention

When it happens

Trigger: GetCertificate forces a refresh and createServerCertificate fails — e.g. the leaf template gets zero/invalid IP or DNS SANs, the CA key algorithm is incompatible, or x509.CreateCertificate returns an error such as 'certificate validity period out of range' due to a bad system clock.

Common situations: Server running on a host whose local IP changed (new SAN) while the CA is malformed, incorrect system clock causing invalid validity windows, or exotic CA keys (e.g. Ed25519 CA with restrictions).

Understand the failure class

Background: "This is a bug, please report it": internal invariant violations, unreachable panics, and SNH errors explained — this error's family across 47 libraries.

Related errors


AI-assisted analysis of siyuan-note/siyuan@8641553a1f (2026-09-11). Data as JSON: /api/errors/3845ccc852144ad5. Report an issue: GitHub.