{"record":{"id":"96b991554054d180","repo":"caddyserver/caddy","slug":"leaf-module-s-is-not-a-leaf-certificate-loader","errorCode":null,"errorMessage":"leaf module '%s' is not a leaf certificate loader","messagePattern":"leaf module '(.+?)' is not a leaf certificate loader","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"modules/caddytls/connpolicy.go","lineNumber":1003,"sourceCode":"\tl.trustedLeafCerts = trustedLeafCertificates\n\treturn nil\n}\n\n// UnmarshalCaddyfile implements caddyfile.Unmarshaler.\nfunc (l *LeafCertClientAuth) UnmarshalCaddyfile(d *caddyfile.Dispenser) error {\n\td.NextArg()\n\n\t// accommodate the use of one-liners\n\tif d.CountRemainingArgs() > 1 {\n\t\td.NextArg()\n\t\tmodName := d.Val()\n\t\tmod, err := caddyfile.UnmarshalModule(d, \"tls.leaf_cert_loader.\"+modName)\n\t\tif err != nil {\n\t\t\treturn d.WrapErr(err)\n\t\t}\n\t\tvMod, ok := mod.(LeafCertificateLoader)\n\t\tif !ok {\n\t\t\treturn fmt.Errorf(\"leaf module '%s' is not a leaf certificate loader\", vMod)\n\t\t}\n\t\tl.LeafCertificateLoadersRaw = append(\n\t\t\tl.LeafCertificateLoadersRaw,\n\t\t\tcaddyconfig.JSONModuleObject(vMod, \"loader\", modName, nil),\n\t\t)\n\t\treturn nil\n\t}\n\n\t// accommodate the use of nested blocks\n\tfor nesting := d.Nesting(); d.NextBlock(nesting); {\n\t\tmodName := d.Val()\n\t\tmod, err := caddyfile.UnmarshalModule(d, \"tls.leaf_cert_loader.\"+modName)\n\t\tif err != nil {\n\t\t\treturn d.WrapErr(err)\n\t\t}\n\t\tvMod, ok := mod.(LeafCertificateLoader)\n\t\tif !ok {\n\t\t\treturn fmt.Errorf(\"leaf module '%s' is not a leaf certificate loader\", vMod)","sourceCodeStart":985,"sourceCodeEnd":1021,"githubUrl":"https://github.com/caddyserver/caddy/blob/50e54ee279aa1e504fe218ca49ab6ae16c100410/modules/caddytls/connpolicy.go#L985-L1021","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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...>"],"exampleFix":null,"handlingStrategy":"type-guard","validationCode":null,"typeGuard":"var _ caddytls.LeafCertificateLoader = (*MyLoader)(nil)\n// implements LoadLeafCertificates() ([]*x509.Certificate, error)\n// and LoadLeafCAPrivateKeys() ([]*ecdsa.PrivateKey, error) per interface","tryCatchPattern":null,"preventionTips":["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"],"tags":["tls","caddyfile","module-system","xcaddy"],"backgroundTag":null,"analyzedSha":"50e54ee279aa1e504fe218ca49ab6ae16c100410","analyzedAt":"2026-08-15T09:20:21.641Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}