{"record":{"id":"45a380eeb0161dde","repo":"caddyserver/caddy","slug":"two-policies-with-same-match-criteria-have-conflic-45a380","errorCode":null,"errorMessage":"two policies with same match criteria have conflicting fallback SNI: %s vs. %s","messagePattern":"two policies with same match criteria have conflicting fallback SNI: (.+?) vs\\. (.+?)","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"caddyconfig/httpcaddyfile/httptype.go","lineNumber":1284,"sourceCode":"\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\",\n\t\t\t\t\t\tcps[i].DefaultSNI, cps[j].DefaultSNI)\n\t\t\t\t}\n\t\t\t\tif cps[i].FallbackSNI != \"\" &&\n\t\t\t\t\tcps[j].FallbackSNI != \"\" &&\n\t\t\t\t\tcps[i].FallbackSNI != cps[j].FallbackSNI {\n\t\t\t\t\treturn nil, fmt.Errorf(\"two policies with same match criteria have conflicting fallback SNI: %s vs. %s\",\n\t\t\t\t\t\tcps[i].FallbackSNI, cps[j].FallbackSNI)\n\t\t\t\t}\n\t\t\t\tif cps[i].ProtocolMin != \"\" &&\n\t\t\t\t\tcps[j].ProtocolMin != \"\" &&\n\t\t\t\t\tcps[i].ProtocolMin != cps[j].ProtocolMin {\n\t\t\t\t\treturn nil, fmt.Errorf(\"two policies with same match criteria have conflicting min protocol: %s vs. %s\",\n\t\t\t\t\t\tcps[i].ProtocolMin, cps[j].ProtocolMin)\n\t\t\t\t}\n\t\t\t\tif cps[i].ProtocolMax != \"\" &&\n\t\t\t\t\tcps[j].ProtocolMax != \"\" &&\n\t\t\t\t\tcps[i].ProtocolMax != cps[j].ProtocolMax {\n\t\t\t\t\treturn nil, fmt.Errorf(\"two policies with same match criteria have conflicting max protocol: %s vs. %s\",\n\t\t\t\t\t\tcps[i].ProtocolMax, cps[j].ProtocolMax)\n\t\t\t\t}\n\t\t\t\tif cps[i].CertSelection != nil && cps[j].CertSelection != nil {\n\t\t\t\t\t// merging fields other than AnyTag is not implemented\n\t\t\t\t\tif !reflect.DeepEqual(cps[i].CertSelection.SerialNumber, cps[j].CertSelection.SerialNumber) ||\n\t\t\t\t\t\t!reflect.DeepEqual(cps[i].CertSelection.SubjectOrganization, cps[j].CertSelection.SubjectOrganization) ||","sourceCodeStart":1266,"sourceCodeEnd":1302,"githubUrl":"https://github.com/caddyserver/caddy/blob/50e54ee279aa1e504fe218ca49ab6ae16c100410/caddyconfig/httpcaddyfile/httptype.go#L1266-L1302","documentation":"Two connection policies matching the same SNI criteria set different non-empty FallbackSNI values. FallbackSNI is used when the ClientHello SNI does not match any configured name; two conflicting fallbacks for the same policy scope cannot be merged.","triggerScenarios":"`fallback_sni` declared in the global options and also (differently) via a tls policy for overlapping names on the same server, or two snippets each setting fallback_sni applied to the same site.","commonSituations":"Adding fallback_sni per-site after already defining it globally with a different value; importing shared snippets that both carry fallback_sni.","solutions":["Define fallback_sni once (global option) and remove per-site duplicates","Make all fallback_sni values identical","Isolate servers needing different fallbacks onto separate listeners"],"exampleFix":"# before\n{\n  fallback_sni a.example.com\n}\nexample.com {\n  tls {\n    # conflicting fallback set here via imported snippet: b.example.com\n  }\n}\n# after\n{\n  fallback_sni a.example.com\n}\nexample.com {\n  respond \"ok\"\n}","handlingStrategy":"validation","validationCode":"assert count_of_fallback_sni_declarations(config) <= 1","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Declare fallback_sni once, globally","Audit snippets for stray fallback_sni when merging","Keep default_sni/fallback_sni decisions in one reviewed file"],"tags":["caddy","tls","sni","caddyfile","conflict"],"backgroundTag":null,"analyzedSha":"50e54ee279aa1e504fe218ca49ab6ae16c100410","analyzedAt":"2026-08-15T09:20:21.641Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}