caddyserver/caddy · error

trust_pool module '%s' is not a certificate pool provider

Error message

trust_pool module '%s' is not a certificate pool provider

What it means

Returned by UnmarshalCaddyfile for client_auth's trust_pool subdirective when the module unmarshaled from tls.ca_pool.source.<name> does not implement the CA interface. Note the message itself is buggy: it formats caMod (a nil-typed interface value) with %s instead of modName, so the name in the message is useless — identify the module from your config instead.

Source

Thrown at modules/caddytls/connpolicy.go:720

			if err != nil {
				return d.WrapErr(err)
			}
			ca.TrustedLeafCerts = append(ca.TrustedLeafCerts, ders...)
		case "trust_pool":
			if len(ca.TrustedCACerts) != 0 {
				return d.Err("cannot specify both 'trust_pool' and 'trusted_ca_cert' or 'trusted_ca_cert_file'")
			}
			if !d.NextArg() {
				return d.ArgErr()
			}
			modName := d.Val()
			mod, err := caddyfile.UnmarshalModule(d, "tls.ca_pool.source."+modName)
			if err != nil {
				return d.WrapErr(err)
			}
			caMod, ok := mod.(CA)
			if !ok {
				return fmt.Errorf("trust_pool module '%s' is not a certificate pool provider", caMod)
			}
			ca.CARaw = caddyconfig.JSONModuleObject(caMod, "provider", modName, nil)
		case "verifier":
			if !d.NextArg() {
				return d.ArgErr()
			}

			vType := d.Val()
			modID := "tls.client_auth.verifier." + vType
			unm, err := caddyfile.UnmarshalModule(d, modID)
			if err != nil {
				return err
			}

			_, ok := unm.(ClientCertificateVerifier)
			if !ok {
				return d.Errf("module '%s' is not a caddytls.ClientCertificateVerifier", modID)
			}

View on GitHub (pinned to 50e54ee279)

Solutions

  1. Look at the argument after 'trust_pool' in your Caddyfile — that is the module name that failed the check (ignore the garbage in the message itself)
  2. Run 'caddy list-modules' and verify the tls.ca_pool.source.<name> module implements the CA pool provider interface
  3. Fix or update the plugin so its module implements CA (Certificates/CACertificates etc.), or use a stock provider
  4. Use 'file', 'inline', 'pki', or 'combined' if they fit your use case

Example fix

# before
client_auth {
	trust_pool mybrokenplugin
}

# after
client_auth {
	trust_pool file /etc/caddy/client-cas.pem
}
Defensive patterns

Strategy: type-guard

Validate before calling

# Before deploying a config with a custom trust_pool provider:
caddy list-modules --packages caddytls | grep 'ca_pool'

Type guard

// Compile-time guard for plugin authors implementing a trust pool source:
var _ caddytls.CA = (*MyPoolSource)(nil)

Prevention

When it happens

Trigger: Writing 'trust_pool <name>' where <name> resolves to a module registered under tls.ca_pool.source but not implementing CA (e.g. a plugin registering a colliding name, or an internal module misused here). Typically only possible with custom builds, since stock source modules (file, inline, combined, root, pki) all implement CA.

Common situations: xcaddy plugin registering a module in the ca_pool namespace without implementing the CA interface; typo happens to match a non-CA module; version skew after a plugin changed its module type.

Understand the failure class

Related errors


AI-assisted analysis of caddyserver/caddy@50e54ee279 (2026-08-15). Data as JSON: /api/errors/0fa35a30991c9514. Report an issue: GitHub.