caddyserver/caddy · error

no sources specified for combined CA pool

Error message

no sources specified for combined CA pool

What it means

The `tls.ca_pool.source.combined` pool requires at least one nested CA pool source, and Provision() rejects a config with an empty SourcesRaw list. A combined pool with no sources would trust nothing, so it is treated as a configuration error.

Source

Thrown at modules/caddytls/capools.go:852

	sources []CA
	pool    *x509.CertPool
	certs   []*x509.Certificate
}

// CaddyModule implements caddy.Module.
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)

View on GitHub (pinned to 50e54ee279)

Solutions

  1. Add at least one source block (file, inline, pki_root, storage, system, http...) inside the combined pool.
  2. If the pool is conditional in generated configs, skip emitting the combined block entirely when the source list is empty.
  3. Run `caddy validate` to catch it before apply.

Example fix

# before
trust_pool combined {
}

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

Strategy: validation

Validate before calling

// generated configs: only emit combined pool when sources exist
if len(sources) == 0 {
	return nil // omit the combined trust pool entirely
}

Prevention

When it happens

Trigger: Configuring `trust_pool combined` with an empty body, or a JSON config where the sources array is absent/empty after templating or snippet expansion.

Common situations: Composable snippets that conditionally include sources but expand to none; placeholder blocks left in configs; automation generating empty combined pools.

Related errors


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