caddyserver/caddy · error
source %T does not implement CertificateProvider (required f
Error message
source %T does not implement CertificateProvider (required for combining)
What it means
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.
Source
Thrown at modules/caddytls/capools.go:873
// Load all source modules
sources, err := ctx.LoadModule(ccp, "SourcesRaw")
if err != nil {
return fmt.Errorf("loading CA pool sources: %v", err)
}
caPool := x509.NewCertPool()
var allCerts []*x509.Certificate
for _, src := range sources.([]any) {
ca, ok := src.(CA)
if !ok {
return fmt.Errorf("source module is not a CA pool provider")
}
ccp.sources = append(ccp.sources, ca)
certProvider, ok := ca.(CertificateProvider)
if !ok {
return fmt.Errorf("source %T does not implement CertificateProvider (required for combining)", ca)
}
certs := certProvider.Certificates()
if certs == nil {
return fmt.Errorf("source %T returned nil certificates", ca)
}
for _, cert := range certs {
if cert == nil {
return fmt.Errorf("source %T returned a nil certificate", ca)
}
caPool.AddCert(cert)
allCerts = append(allCerts, cert)
}
}
ccp.pool = caPool
ccp.certs = allCerts
View on GitHub (pinned to 50e54ee279)
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.
Example fix
// before
type MyPool struct{}
func (m MyPool) CertPool() *x509.CertPool { return m.pool }
// after
type MyPool struct{ pool *x509.CertPool; certs []*x509.Certificate }
func (m MyPool) CertPool() *x509.CertPool { return m.pool }
func (m MyPool) Certificates() []*x509.Certificate { return m.certs } Defensive patterns
Strategy: type-guard
Type guard
// compile-time guarantee that a custom pool satisfies both interfaces var ( _ caddytls.CA = (*MyPool)(nil) _ caddytls.CertificateProvider = (*MyPool)(nil) )
Prevention
- 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.
When it happens
Trigger: 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.
Common situations: Plugin modules written against an older API surface; custom pool sources written without the CertificateProvider method.
Understand the failure class
- SSL/TLS and certificate errors — how TLS handshakes and certificate validation fail.
Related errors
- source %T returned nil certificates
- module %s is not a precompressor; is %T
- no sources specified for combined CA pool
- loading CA pool sources: %v
- source module is not a CA pool provider
AI-assisted analysis of caddyserver/caddy@50e54ee279 (2026-08-15).
Data as JSON: /api/errors/59215a2b5844556a.
Report an issue: GitHub.