{"record":{"id":"174c83d936b1b61e","repo":"caddyserver/caddy","slug":"consolidating-tls-connection-policies-for-server","errorCode":null,"errorMessage":"consolidating TLS connection policies for server %d: %v","messagePattern":"consolidating TLS connection policies for server (.+?): (.+?)","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"caddyconfig/httpcaddyfile/httptype.go","lineNumber":1105,"sourceCode":"\t\t// catch-all/default policy if there isn't one already (it's\n\t\t// important that it goes at the end) - see issue #3004:\n\t\t// https://github.com/caddyserver/caddy/issues/3004\n\t\t// TODO: maybe a smarter way to handle this might be to just make the\n\t\t// auto-HTTPS logic at provision-time detect if there is any connection\n\t\t// policy missing for any HTTPS-enabled hosts, if so, add it... maybe?\n\t\tif addressQualifiesForTLS &&\n\t\t\t!hasCatchAllTLSConnPolicy &&\n\t\t\t(len(srv.TLSConnPolicies) > 0 || !autoHTTPSWillAddConnPolicy || defaultSNI != \"\" || fallbackSNI != \"\") {\n\t\t\tsrv.TLSConnPolicies = append(srv.TLSConnPolicies, &caddytls.ConnectionPolicy{\n\t\t\t\tDefaultSNI:  defaultSNI,\n\t\t\t\tFallbackSNI: fallbackSNI,\n\t\t\t})\n\t\t}\n\n\t\t// tidy things up a bit\n\t\tsrv.TLSConnPolicies, err = consolidateConnPolicies(srv.TLSConnPolicies)\n\t\tif err != nil {\n\t\t\treturn nil, fmt.Errorf(\"consolidating TLS connection policies for server %d: %v\", i, err)\n\t\t}\n\t\tsrv.Routes = consolidateRoutes(srv.Routes)\n\n\t\tservers[fmt.Sprintf(\"srv%d\", i)] = srv\n\t}\n\n\tif err := applyServerOptions(servers, options, warnings); err != nil {\n\t\treturn nil, fmt.Errorf(\"applying global server options: %v\", err)\n\t}\n\n\treturn servers, nil\n}\n\n// sniNames returns the server names a connection policy's sni matcher matches.\n// The bool is false when the policy has no sni matcher, or when it does not\n// decode - the latter is unexpected enough to warn about rather than silently\n// skip, since callers use it to decide whether a hostname needs shielding.\nfunc sniNames(cp *caddytls.ConnectionPolicy, what string, warnings *[]caddyconfig.Warning) ([]string, bool) {","sourceCodeStart":1087,"sourceCodeEnd":1123,"githubUrl":"https://github.com/caddyserver/caddy/blob/50e54ee279aa1e504fe218ca49ab6ae16c100410/caddyconfig/httpcaddyfile/httptype.go#L1087-L1123","documentation":"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.","triggerScenarios":"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).","commonSituations":"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.","solutions":["Make the tls settings identical for all site blocks that share the same hostnames (or delete the duplicated ones so a single policy remains)","Use different ports or explicit `bind`/server splits so conflicting policies land on different servers instead of being consolidated","Set the conflicting option once in the global `default_sni`/`fallback_sni` options rather than per site","Check the server index (srv0, srv1, ...) in the message to identify which listen group has the clash"],"exampleFix":"# before\nexample.com {\n  tls {\n    protocols tls1.2\n  }\n}\nexample.com:8443 {\n  tls {\n    protocols tls1.3\n  }\n}\n# after\nexample.com {\n  tls {\n    protocols tls1.2 tls1.3\n  }\n}","handlingStrategy":"validation","validationCode":"# Deduplicate tls settings per hostname before adapting; a quick lint pass:\n# (conceptual, in your config pipeline)\nassert len({block.tls_settings for block in blocks if block.host == host}) <= 1","typeGuard":null,"tryCatchPattern":"if err := caddyfileAdapt(cfg); err != nil {\n    if strings.Contains(err.Error(), \"consolidating TLS connection policies\") {\n        // surface which server index and dedupe tls blocks\n    }\n}","preventionTips":["Keep each hostname's tls block in one place (snippet) and import it","Run `caddy adapt --config Caddyfile` in CI to catch consolidation conflicts before deploy","Avoid mixing global default_sni/fallback_sni with per-site tls overrides"],"tags":["caddy","tls","config","caddyfile"],"backgroundTag":null,"analyzedSha":"50e54ee279aa1e504fe218ca49ab6ae16c100410","analyzedAt":"2026-08-15T09:20:21.641Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}