caddyserver/caddy · error
two policies with same match criteria have conflicting defau
Error message
two policies with same match criteria have conflicting default SNI: %s vs. %s
What it means
Two connection policies with identical match criteria both set a non-empty DefaultSNI and the values differ. DefaultSNI decides which certificate to serve when a client sends no SNI; two different defaults for the same matched connections are irreconcilable.
Source
Thrown at caddyconfig/httpcaddyfile/httptype.go:1278
return nil, fmt.Errorf("two policies with same match criteria have conflicting cipher suites: %v vs. %v",
cps[i].CipherSuites, cps[j].CipherSuites)
}
if cps[i].ClientAuthentication == nil &&
cps[j].ClientAuthentication != nil &&
!reflect.DeepEqual(cps[i].ClientAuthentication, cps[j].ClientAuthentication) {
return nil, fmt.Errorf("two policies with same match criteria have conflicting client auth configuration: %+v vs. %+v",
cps[i].ClientAuthentication, cps[j].ClientAuthentication)
}
if len(cps[i].Curves) > 0 &&
len(cps[j].Curves) > 0 &&
!reflect.DeepEqual(cps[i].Curves, cps[j].Curves) {
return nil, fmt.Errorf("two policies with same match criteria have conflicting curves: %v vs. %v",
cps[i].Curves, cps[j].Curves)
}
if cps[i].DefaultSNI != "" &&
cps[j].DefaultSNI != "" &&
cps[i].DefaultSNI != cps[j].DefaultSNI {
return nil, fmt.Errorf("two policies with same match criteria have conflicting default SNI: %s vs. %s",
cps[i].DefaultSNI, cps[j].DefaultSNI)
}
if cps[i].FallbackSNI != "" &&
cps[j].FallbackSNI != "" &&
cps[i].FallbackSNI != cps[j].FallbackSNI {
return nil, fmt.Errorf("two policies with same match criteria have conflicting fallback SNI: %s vs. %s",
cps[i].FallbackSNI, cps[j].FallbackSNI)
}
if cps[i].ProtocolMin != "" &&
cps[j].ProtocolMin != "" &&
cps[i].ProtocolMin != cps[j].ProtocolMin {
return nil, fmt.Errorf("two policies with same match criteria have conflicting min protocol: %s vs. %s",
cps[i].ProtocolMin, cps[j].ProtocolMin)
}
if cps[i].ProtocolMax != "" &&
cps[j].ProtocolMax != "" &&
cps[i].ProtocolMax != cps[j].ProtocolMax {
return nil, fmt.Errorf("two policies with same match criteria have conflicting max protocol: %s vs. %s",View on GitHub (pinned to 50e54ee279)
Solutions
- Set default_sni in exactly one place (prefer the global option) and delete per-site duplicates
- Align the values if both are intentional
- Use separate servers per listen address if different defaults are truly needed
Example fix
# before
{
default_sni a.example.com
}
example.com {
# snippet also sets default_sni b.example.com
}
# after
{
default_sni a.example.com
}
example.com {
respond "ok"
} Defensive patterns
Strategy: validation
Validate before calling
# Exactly one default_sni source assert count_of_default_sni_declarations(config) <= 1
Prevention
- Set default_sni only in the global options
- Do not copy default_sni into imported snippets
- Grep configs for default_sni before merging files
When it happens
Trigger: The global `default_sni` option combined with a site block or connection policy that sets a different default_sni for the same server — e.g. `{ default_sni a.example.com }` globally while a `tls { default_sni b.example.com }` style policy on matching names produces a second policy with the same matchers.
Common situations: Setting default_sni both globally and per-site (or in multiple imported snippets) with inconsistent values that end up on one server.
Related errors
- two policies with same match criteria have conflicting fallb
- server listening on %v is HTTP, but attempts to configure TL
- two policies with same match criteria have conflicting ALPN:
- two policies with same match criteria have conflicting ciphe
- two policies with same match criteria have conflicting curve
AI-assisted analysis of caddyserver/caddy@50e54ee279 (2026-08-15).
Data as JSON: /api/errors/6a8b2d3c40b1562f.
Report an issue: GitHub.