{"record":{"id":"59215a2b5844556a","repo":"caddyserver/caddy","slug":"source-t-does-not-implement-certificateprovider","errorCode":null,"errorMessage":"source %T does not implement CertificateProvider (required for combining)","messagePattern":"source %T does not implement CertificateProvider \\(required for combining\\)","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"modules/caddytls/capools.go","lineNumber":873,"sourceCode":"\t// Load all source modules\n\tsources, err := ctx.LoadModule(ccp, \"SourcesRaw\")\n\tif err != nil {\n\t\treturn fmt.Errorf(\"loading CA pool sources: %v\", err)\n\t}\n\n\tcaPool := x509.NewCertPool()\n\tvar allCerts []*x509.Certificate\n\n\tfor _, src := range sources.([]any) {\n\t\tca, ok := src.(CA)\n\t\tif !ok {\n\t\t\treturn fmt.Errorf(\"source module is not a CA pool provider\")\n\t\t}\n\t\tccp.sources = append(ccp.sources, ca)\n\n\t\tcertProvider, ok := ca.(CertificateProvider)\n\t\tif !ok {\n\t\t\treturn fmt.Errorf(\"source %T does not implement CertificateProvider (required for combining)\", ca)\n\t\t}\n\n\t\tcerts := certProvider.Certificates()\n\t\tif certs == nil {\n\t\t\treturn fmt.Errorf(\"source %T returned nil certificates\", ca)\n\t\t}\n\t\tfor _, cert := range certs {\n\t\t\tif cert == nil {\n\t\t\t\treturn fmt.Errorf(\"source %T returned a nil certificate\", ca)\n\t\t\t}\n\t\t\tcaPool.AddCert(cert)\n\t\t\tallCerts = append(allCerts, cert)\n\t\t}\n\t}\n\n\tccp.pool = caPool\n\tccp.certs = allCerts\n","sourceCodeStart":855,"sourceCodeEnd":891,"githubUrl":"https://github.com/caddyserver/caddy/blob/50e54ee279aa1e504fe218ca49ab6ae16c100410/modules/caddytls/capools.go#L855-L891","documentation":"Every source inside a combined CA pool must also implement the optional CertificateProvider interface (Certificates() []*x509.Certificate) so the combined pool can enumerate and merge the underlying certs. A source that only implements CA cannot be combined and triggers this error.","triggerScenarios":"Embedding a third-party or custom CA pool module that implements CertPool() but not Certificates() and using it as a source of a combined pool. All built-in pools implement both, so this is a custom-module issue.","commonSituations":"Plugin modules written against an older API surface; custom pool sources written without the CertificateProvider method.","solutions":["Update the custom/plugin pool module to implement Certificates() []*x509.Certificate alongside CertPool().","Alternatively, do not use that module inside a combined pool — reference it directly as the trust pool.","Check the plugin's repo for a newer release matching your Caddy version."],"exampleFix":"// before\ntype MyPool struct{}\nfunc (m MyPool) CertPool() *x509.CertPool { return m.pool }\n\n// after\ntype MyPool struct{ pool *x509.CertPool; certs []*x509.Certificate }\nfunc (m MyPool) CertPool() *x509.CertPool { return m.pool }\nfunc (m MyPool) Certificates() []*x509.Certificate { return m.certs }","handlingStrategy":"type-guard","validationCode":null,"typeGuard":"// compile-time guarantee that a custom pool satisfies both interfaces\nvar (\n\t_ caddytls.CA                 = (*MyPool)(nil)\n\t_ caddytls.CertificateProvider = (*MyPool)(nil)\n)","tryCatchPattern":null,"preventionTips":["Add the compile-time interface guards (shown above) to every custom pool module.","Run the module's unit tests inside a config that uses it under trust_pool combined.","Keep plugins updated with the Caddy version whose caddytls API they target."],"tags":["caddy","caddytls","interface","plugin","combined-pool"],"backgroundTag":null,"analyzedSha":"50e54ee279aa1e504fe218ca49ab6ae16c100410","analyzedAt":"2026-08-15T09:20:21.641Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}