caddyserver/caddy · error

consolidating TLS connection policies for server %d: %v

Error message

consolidating TLS connection policies for server %d: %v

What it means

Caddyfile adaptation failed while merging/normalizing the TLS connection policies collected for one HTTP server (srv%d). consolidateConnPolicies tries to combine policies that match the same SNI set; if two such policies disagree on a setting that cannot be safely merged (e.g. different ALPN, cipher suites, protocols, client auth), it returns an error that gets wrapped with the server index.

Source

Thrown at caddyconfig/httpcaddyfile/httptype.go:1105

		// catch-all/default policy if there isn't one already (it's
		// important that it goes at the end) - see issue #3004:
		// https://github.com/caddyserver/caddy/issues/3004
		// TODO: maybe a smarter way to handle this might be to just make the
		// auto-HTTPS logic at provision-time detect if there is any connection
		// policy missing for any HTTPS-enabled hosts, if so, add it... maybe?
		if addressQualifiesForTLS &&
			!hasCatchAllTLSConnPolicy &&
			(len(srv.TLSConnPolicies) > 0 || !autoHTTPSWillAddConnPolicy || defaultSNI != "" || fallbackSNI != "") {
			srv.TLSConnPolicies = append(srv.TLSConnPolicies, &caddytls.ConnectionPolicy{
				DefaultSNI:  defaultSNI,
				FallbackSNI: fallbackSNI,
			})
		}

		// tidy things up a bit
		srv.TLSConnPolicies, err = consolidateConnPolicies(srv.TLSConnPolicies)
		if err != nil {
			return nil, fmt.Errorf("consolidating TLS connection policies for server %d: %v", i, err)
		}
		srv.Routes = consolidateRoutes(srv.Routes)

		servers[fmt.Sprintf("srv%d", i)] = srv
	}

	if err := applyServerOptions(servers, options, warnings); err != nil {
		return nil, fmt.Errorf("applying global server options: %v", err)
	}

	return servers, nil
}

// sniNames returns the server names a connection policy's sni matcher matches.
// The bool is false when the policy has no sni matcher, or when it does not
// decode - the latter is unexpected enough to warn about rather than silently
// skip, since callers use it to decide whether a hostname needs shielding.
func sniNames(cp *caddytls.ConnectionPolicy, what string, warnings *[]caddyconfig.Warning) ([]string, bool) {

View on GitHub (pinned to 50e54ee279)

Solutions

  1. Make the tls settings identical for all site blocks that share the same hostnames (or delete the duplicated ones so a single policy remains)
  2. Use different ports or explicit `bind`/server splits so conflicting policies land on different servers instead of being consolidated
  3. Set the conflicting option once in the global `default_sni`/`fallback_sni` options rather than per site
  4. Check the server index (srv0, srv1, ...) in the message to identify which listen group has the clash

Example fix

# before
example.com {
  tls {
    protocols tls1.2
  }
}
example.com:8443 {
  tls {
    protocols tls1.3
  }
}
# after
example.com {
  tls {
    protocols tls1.2 tls1.3
  }
}
Defensive patterns

Strategy: validation

Validate before calling

# Deduplicate tls settings per hostname before adapting; a quick lint pass:
# (conceptual, in your config pipeline)
assert len({block.tls_settings for block in blocks if block.host == host}) <= 1

Try / catch

if err := caddyfileAdapt(cfg); err != nil {
    if strings.Contains(err.Error(), "consolidating TLS connection policies") {
        // surface which server index and dedupe tls blocks
    }
}

Prevention

When it happens

Trigger: A site block whose server (same listen port group) ends up with two or more tls connection policies covering overlapping/same SNI matchers with incompatible settings — e.g. one block sets `tls { protocols }` and another with the same hostname sets `tls { ciphers }` or different `alpn`, so consolidation cannot reconcile them. Also any error surfaced by the per-field conflict checks inside consolidateConnPolicies (errors 127-135).

Common situations: Multiple site blocks on the same port declaring different `tls` settings for the same domain, a global `tls`/`default_sni` global option combined with per-site `tls` blocks that conflict, or copy-pasted site configs where one block has `tls internal` and another has explicit ciphers for the same names.

Understand the failure class

Related errors


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