{"record":{"id":"bf33c973bd8be0a5","repo":"caddyserver/caddy","slug":"two-policies-with-same-match-criteria-have-conflic-bf33c9","errorCode":null,"errorMessage":"two policies with same match criteria have conflicting cipher suites: %v vs. %v","messagePattern":"two policies with same match criteria have conflicting cipher suites: (.+?) vs\\. (.+?)","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"caddyconfig/httpcaddyfile/httptype.go","lineNumber":1260,"sourceCode":"\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// if they have the same matcher, try to reconcile each field: either they must\n\t\t\t// be identical, or we have to be able to combine them safely\n\t\t\tif reflect.DeepEqual(cps[i].MatchersRaw, cps[j].MatchersRaw) {\n\t\t\t\tif len(cps[i].ALPN) > 0 &&\n\t\t\t\t\tlen(cps[j].ALPN) > 0 &&\n\t\t\t\t\t!reflect.DeepEqual(cps[i].ALPN, cps[j].ALPN) {\n\t\t\t\t\treturn nil, fmt.Errorf(\"two policies with same match criteria have conflicting ALPN: %v vs. %v\",\n\t\t\t\t\t\tcps[i].ALPN, cps[j].ALPN)\n\t\t\t\t}\n\t\t\t\tif len(cps[i].CipherSuites) > 0 &&\n\t\t\t\t\tlen(cps[j].CipherSuites) > 0 &&\n\t\t\t\t\t!reflect.DeepEqual(cps[i].CipherSuites, cps[j].CipherSuites) {\n\t\t\t\t\treturn nil, fmt.Errorf(\"two policies with same match criteria have conflicting cipher suites: %v vs. %v\",\n\t\t\t\t\t\tcps[i].CipherSuites, cps[j].CipherSuites)\n\t\t\t\t}\n\t\t\t\tif cps[i].ClientAuthentication == nil &&\n\t\t\t\t\tcps[j].ClientAuthentication != nil &&\n\t\t\t\t\t!reflect.DeepEqual(cps[i].ClientAuthentication, cps[j].ClientAuthentication) {\n\t\t\t\t\treturn nil, fmt.Errorf(\"two policies with same match criteria have conflicting client auth configuration: %+v vs. %+v\",\n\t\t\t\t\t\tcps[i].ClientAuthentication, cps[j].ClientAuthentication)\n\t\t\t\t}\n\t\t\t\tif len(cps[i].Curves) > 0 &&\n\t\t\t\t\tlen(cps[j].Curves) > 0 &&\n\t\t\t\t\t!reflect.DeepEqual(cps[i].Curves, cps[j].Curves) {\n\t\t\t\t\treturn nil, fmt.Errorf(\"two policies with same match criteria have conflicting curves: %v vs. %v\",\n\t\t\t\t\t\tcps[i].Curves, cps[j].Curves)\n\t\t\t\t}\n\t\t\t\tif cps[i].DefaultSNI != \"\" &&\n\t\t\t\t\tcps[j].DefaultSNI != \"\" &&\n\t\t\t\t\tcps[i].DefaultSNI != cps[j].DefaultSNI {\n\t\t\t\t\treturn nil, fmt.Errorf(\"two policies with same match criteria have conflicting default SNI: %s vs. %s\",","sourceCodeStart":1242,"sourceCodeEnd":1278,"githubUrl":"https://github.com/caddyserver/caddy/blob/50e54ee279aa1e504fe218ca49ab6ae16c100410/caddyconfig/httpcaddyfile/httptype.go#L1242-L1278","documentation":"Two TLS connection policies with identical SNI match criteria specify different non-empty cipher suite lists. The adapter will not silently choose one cipher list for a handshake both policies govern, so it aborts with the two lists printed for comparison.","triggerScenarios":"Same-hostname site blocks with `tls { ciphers ... }` listing different suites (e.g. one modern list, one including TLS_RSA suites), or a site-level ciphers setting conflicting with a snippet/global tls policy applied to the same names on the same server.","commonSituations":"Copy-pasted legacy cipher lists pasted into two blocks for the same domain, snippets imported into multiple site blocks with per-import cipher overrides, or migrating cipher config between versions leaving a stale duplicate block.","solutions":["Use one identical `ciphers` list everywhere the hostname appears","Remove ciphers entirely to accept Caddy defaults (recommended)","Delete or deduplicate the redundant site block","Put the conflicting sites on separate servers (distinct ports/binds)"],"exampleFix":"# before\nexample.com {\n  tls {\n    ciphers TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256\n  }\n}\nexample.com {\n  tls {\n    ciphers TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384\n  }\n}\n# after\nexample.com {\n  tls {\n    ciphers TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384\n  }\n}","handlingStrategy":"validation","validationCode":"# One ciphers list per hostname across all blocks\nfor h, lists in group_ciphers_by_host(sites).items():\n    assert len({tuple(l) for l in lists if l}) <= 1, f'conflicting ciphers for {h}'","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Prefer Caddy's default cipher suites unless required","Centralize tls settings in snippets imported by all blocks","Avoid pasting legacy cipher lists into multiple blocks"],"tags":["caddy","tls","ciphers","caddyfile","conflict"],"backgroundTag":null,"analyzedSha":"50e54ee279aa1e504fe218ca49ab6ae16c100410","analyzedAt":"2026-08-15T09:20:21.641Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}