caddyserver/caddy · error
caching unmanaged certificate: %v
Error message
caching unmanaged certificate: %v
What it means
Each certificate returned by a loader is put into the shared certmagic cache via magic.CacheUnmanagedTLSCertificate. This error means certmagic rejected the parsed certificate: commonly the leaf certificate is not valid for any names, is expired in a way certmagic rejects, has no names extractable from SANs/CN, or the TLS handshake configuration it builds (key type) is unsupported.
Source
Thrown at modules/caddytls/tls.go:271
magic := certmagic.New(certCache, certmagic.Config{
Storage: ctx.Storage(),
Logger: t.logger,
OnEvent: t.onEvent,
OCSP: certmagic.OCSPConfig{
DisableStapling: t.DisableOCSPStapling,
},
DisableStorageCheck: t.DisableStorageCheck,
})
certCacheMu.RUnlock()
for _, loader := range t.certificateLoaders {
certs, err := loader.LoadCertificates()
if err != nil {
return fmt.Errorf("loading certificates: %v", err)
}
for _, cert := range certs {
hash, err := magic.CacheUnmanagedTLSCertificate(ctx, cert.Certificate, cert.Tags)
if err != nil {
return fmt.Errorf("caching unmanaged certificate: %v", err)
}
t.loaded[hash] = ""
}
}
// on-demand permission module
if t.Automation != nil && t.Automation.OnDemand != nil && t.Automation.OnDemand.PermissionRaw != nil {
if t.Automation.OnDemand.Ask != "" {
return fmt.Errorf("on-demand TLS config conflict: both 'ask' endpoint and a 'permission' module are specified; 'ask' is deprecated, so use only the permission module")
}
val, err := ctx.LoadModule(t.Automation.OnDemand, "PermissionRaw")
if err != nil {
return fmt.Errorf("loading on-demand TLS permission module: %v", err)
}
t.Automation.OnDemand.permission = val.(OnDemandPermission)
}
// automation/management policiesView on GitHub (pinned to 50e54ee279)
Solutions
- Inspect the wrapped error from certmagic; it distinguishes parse vs. handshake-configuration failures
- Inspect the cert: 'openssl x509 -in cert.pem -noout -text' — confirm SAN entries exist and cover intended names
- Re-encode the key/cert to standard RSA-2048/ECDSA PEM if produced by exotic tooling
- Confirm the key file passed alongside actually corresponds to the certificate
Example fix
# before: cert with no SAN, only CN (rejected) $ openssl req -x509 -newkey rsa:2048 -nodes -keyout k.pem -out c.pem -subj "/CN=example.com" # after: include SAN $ openssl req -x509 -newkey rsa:2048 -nodes -keyout k.pem -out c.pem -subj "/CN=example.com" -addext "subjectAltName=DNS:example.com"
Defensive patterns
Strategy: validation
Validate before calling
openssl x509 -in cert.pem -noout -ext subjectAltName # must list DNS names openssl verify -CAfile cert.pem cert.pem
Prevention
- Always generate certs with explicit SANs; CN-only certs are rejected
- Verify cert/key pairing (matching modulus) before deploying
When it happens
Trigger: Loading a cert whose SAN list is empty; a certificate parsed but whose tags/names cannot be determined; an unsupported private key algorithm (e.g. Ed448 or an encrypted PKCS#8 key that cannot be loaded); corrupted DER inside an otherwise valid PEM envelope.
Common situations: Self-generated certs created with unusual OpenSSL options; certs from HSMs or cloud services exported in non-standard ways; mixing up certificate and key file order in load_files entries.
Understand the failure class
- SSL/TLS and certificate errors — how TLS handshakes and certificate validation fail.
Related errors
- no CERTIFICATE pem block found in %s
- loading certificates: %v
- creating storage value: %v
- consolidating TLS connection policies for server %d: %v
- server listening on %v is HTTP, but attempts to configure TL
AI-assisted analysis of caddyserver/caddy@50e54ee279 (2026-08-15).
Data as JSON: /api/errors/7caa836a2f98323b.
Report an issue: GitHub.