AdguardTeam/AdGuardHome · critical
parsing tls certificate: %w
Error message
parsing tls certificate: %w
What it means
prepareTLSConfig (used by NewDefaultManager) loads and parses the configured TLS certificate with tls.X509KeyPair-style parsing; failure here means the certificate or key material couldn't be parsed — malformed PEM, missing blocks, or key/cert mismatch. External TLS is disabled as a side effect (mgr.extTLSConf.Enabled = false).
Source
Thrown at internal/aghtls/defaultmanager.go:163
mgr.extTLSConf.Enabled = false
// Don't wrap the error, because it's informative enough as is.
return err
}
cert, err := tls.X509KeyPair(mgr.extTLSConf.CertificateChainData, mgr.extTLSConf.PrivateKeyData)
if err != nil {
// DNSCrypt provides its own certificate, meaning we can ignore TLS
// certificate parsing errors.
if mgr.extTLSConf.PortDNSCrypt != 0 && mgr.extTLSConf.DNSCryptConfigFile != "" {
mgr.logger.InfoContext(ctx, "dnscrypt is configured")
return nil
}
mgr.extTLSConf.Enabled = false
return fmt.Errorf("parsing tls certificate: %w", err)
}
slices.Sort(cert.Leaf.DNSNames)
mgr.tlsCert = &cert
mgr.setCertFileTime(ctx)
mgr.tlsConf = &tls.Config{
RootCAs: mgr.rootCerts,
CipherSuites: mgr.customCipherIDs,
GetCertificate: mgr.onGetCertificate,
MinVersion: tls.VersionTLS12,
}
return nil
}
// type check
var _ Manager = (*DefaultManager)(nil)View on GitHub (pinned to b41aefbe51)
Solutions
- Validate the pair offline: openssl x509 -in cert.pem -noout and openssl rsa -in key.pem -check
- Confirm cert and key match: compare openssl x509 -noout -modulus | openssl md5 for both (or pkey for RSA alternatives)
- Re-export/re-issue the pair as unencrypted PEM and update the config paths
- After fixing, restart so NewDefaultManager re-attempts loading
Example fix
# verify match openssl x509 -in cert.pem -noout -modulus | openssl md5 openssl rsa -in key.pem -noout -modulus | openssl md5
Defensive patterns
Strategy: validation
Validate before calling
// verify pair parses and matches before starting the manager:
if _, err := tls.X509KeyPair(certPEM, keyPEM); err != nil { return fmt.Errorf("invalid pair: %w", err) } Type guard
func certMatchesKey(certPEM, keyPEM []byte) bool { _, err := tls.X509KeyPair(certPEM, keyPEM); return err == nil } Try / catch
mgr, err := aghtls.NewDefaultManager(...)
if err != nil && strings.Contains(err.Error(), "parsing tls certificate") {
// fail startup, keep HTTP-only, alert operator; external TLS is disabled by this point
} Prevention
- Validate cert/key pairs at deploy time with openssl
- Automate renewal so hand-pasted PEM truncation can't happen
- Monitor certificate expiry and reload health after rotation
- Never mix cert/key from different issuance batches
When it happens
Trigger: NewDefaultManager with a certificate file or key that isn't valid PEM, where the key doesn't match the certificate, where either file is empty/truncated, or where the key is encrypted and can't be decoded; also file read issues upstream surface wrapped here.
Common situations: Expired-then-regenerated certs pasted with truncated headers; cert and key from different issuance rounds; wrong file paths yielding empty content; keys in PKCS#12 or unusual formats instead of PEM.
Understand the failure class
- SSL/TLS and certificate errors — how TLS handshakes and certificate validation fail.
Related errors
- loading tls certificate: %w
- parsing certificate at index %d: %w
- certificate does not verify: %w
- certificate-key pair: %w
- validating tcp ports: %w
AI-assisted analysis of AdguardTeam/AdGuardHome@b41aefbe51 (2026-08-27).
Data as JSON: /api/errors/98dee07ee04ae3cc.
Report an issue: GitHub.