caddyserver/caddy · error
leaf module '%s' is not a leaf certificate loader
Error message
leaf module '%s' is not a leaf certificate loader
What it means
During Caddyfile parsing of the leaf verifier one-liner form (verifier leaf <inline|file> <arg...>), the unmarshaled module must implement the LeafCertificateLoader interface; if it does not, this error is returned. With stock builds this indicates a broken/misregistered plugin; the %s formats the module value, which may print unhelpfully.
Source
Thrown at modules/caddytls/connpolicy.go:1003
l.trustedLeafCerts = trustedLeafCertificates
return nil
}
// UnmarshalCaddyfile implements caddyfile.Unmarshaler.
func (l *LeafCertClientAuth) UnmarshalCaddyfile(d *caddyfile.Dispenser) error {
d.NextArg()
// accommodate the use of one-liners
if d.CountRemainingArgs() > 1 {
d.NextArg()
modName := d.Val()
mod, err := caddyfile.UnmarshalModule(d, "tls.leaf_cert_loader."+modName)
if err != nil {
return d.WrapErr(err)
}
vMod, ok := mod.(LeafCertificateLoader)
if !ok {
return fmt.Errorf("leaf module '%s' is not a leaf certificate loader", vMod)
}
l.LeafCertificateLoadersRaw = append(
l.LeafCertificateLoadersRaw,
caddyconfig.JSONModuleObject(vMod, "loader", modName, nil),
)
return nil
}
// accommodate the use of nested blocks
for nesting := d.Nesting(); d.NextBlock(nesting); {
modName := d.Val()
mod, err := caddyfile.UnmarshalModule(d, "tls.leaf_cert_loader."+modName)
if err != nil {
return d.WrapErr(err)
}
vMod, ok := mod.(LeafCertificateLoader)
if !ok {
return fmt.Errorf("leaf module '%s' is not a leaf certificate loader", vMod)View on GitHub (pinned to 50e54ee279)
Solutions
- If this is your plugin, implement the full LeafCertificateLoader interface and add a compile-time guard: var _ caddytls.LeafCertificateLoader = (*MyLoader)(nil)
- Rebuild with xcaddy against the Caddy version you deploy; mismatched ABI/module interfaces often surface here
- If using only stock loaders, rebuild without stale custom plugins and retry
- Check the Caddyfile syntax matches: leaf_cert inline <b64der> or leaf_cert file <paths...>
Defensive patterns
Strategy: type-guard
Type guard
var _ caddytls.LeafCertificateLoader = (*MyLoader)(nil) // implements LoadLeafCertificates() ([]*x509.Certificate, error) // and LoadLeafCAPrivateKeys() ([]*ecdsa.PrivateKey, error) per interface
Prevention
- Add interface guards to every custom tls.leaf_cert_loader plugin
- Prefer the stock inline/file loaders unless you need custom sourcing
- Rebuild plugins against each new Caddy minor version
When it happens
Trigger: A custom module registered under tls.leaf_cert_loader.* that does not implement LoadLeafCertificates()/LoadLeafCAPrivateKeys(); name collisions where the resolved module is the wrong type.
Common situations: XCaddy plugin development where the interface is not yet implemented; plugin builds where an old version of a plugin diverged from the expected interface after a Caddy upgrade.
Understand the failure class
- SSL/TLS and certificate errors — how TLS handshakes and certificate validation fail.
Related errors
- matcher module '%s' is not a connection matcher
- 'ca' module '%s' is not a certificate pool provider
- marshaling %T matcher: %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/96b991554054d180.
Report an issue: GitHub.