caddyserver/caddy · error

loading CA pool sources: %v

Error message

loading CA pool sources: %v

What it means

While provisioning a combined CA pool, ctx.LoadModule on the nested SourcesRaw list failed. This wraps errors from loading each child source module — unknown module IDs, invalid child config, or a child source's own provisioning error.

Source

Thrown at modules/caddytls/capools.go:858

func (CombinedCAPool) CaddyModule() caddy.ModuleInfo {
	return caddy.ModuleInfo{
		ID: "tls.ca_pool.source.combined",
		New: func() caddy.Module {
			return new(CombinedCAPool)
		},
	}
}

// Provision implements caddy.Provisioner.
func (ccp *CombinedCAPool) Provision(ctx caddy.Context) error {
	if len(ccp.SourcesRaw) == 0 {
		return fmt.Errorf("no sources specified for combined CA pool")
	}

	// 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()

View on GitHub (pinned to 50e54ee279)

Solutions

  1. Read the wrapped error — it identifies which child module failed and why; fix that source's name or config.
  2. If the source comes from a plugin, rebuild with xcaddy including the plugin.
  3. Confirm module IDs with `caddy list-modules | grep ca_pool.source`.

Example fix

# before
trust_pool combined {
  fille /etc/caddy/roots.pem
}

# after
trust_pool combined {
  file /etc/caddy/roots.pem
}
Defensive patterns

Strategy: validation

Validate before calling

// confirm every referenced source module id exists in this build
// after building: `caddy list-modules | grep 'tls.ca_pool.source'`
// programmatically, keep a set of allowed sources and check generated configs against it:
var allowedSources = map[string]bool{
	"tls.ca_pool.source.file": true,
	"tls.ca_pool.source.inline": true,
	"tls.ca_pool.source.pki_root": true,
	"tls.ca_pool.source.pki_intermediate": true,
	"tls.ca_pool.source.storage": true,
	"tls.ca_pool.source.http": true,
	"tls.ca_pool.source.system": true,
}

Prevention

When it happens

Trigger: A source inside `trust_pool combined { ... }` whose module name is not registered (e.g. `http` misspelled, or a plugin-based pool not compiled in), or whose own configuration is invalid so its Provision fails.

Common situations: Custom builds missing a plugin module referenced in the combined block; typos in source names; child source blocks with bad arguments that fail during load.

Related errors


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