caddyserver/caddy · error
two policies with same match criteria have conflicting ciphe
Error message
two policies with same match criteria have conflicting cipher suites: %v vs. %v
What it means
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.
Source
Thrown at caddyconfig/httpcaddyfile/httptype.go:1260
}
}
}
}
}
// if they have the same matcher, try to reconcile each field: either they must
// be identical, or we have to be able to combine them safely
if reflect.DeepEqual(cps[i].MatchersRaw, cps[j].MatchersRaw) {
if len(cps[i].ALPN) > 0 &&
len(cps[j].ALPN) > 0 &&
!reflect.DeepEqual(cps[i].ALPN, cps[j].ALPN) {
return nil, fmt.Errorf("two policies with same match criteria have conflicting ALPN: %v vs. %v",
cps[i].ALPN, cps[j].ALPN)
}
if len(cps[i].CipherSuites) > 0 &&
len(cps[j].CipherSuites) > 0 &&
!reflect.DeepEqual(cps[i].CipherSuites, cps[j].CipherSuites) {
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",View on GitHub (pinned to 50e54ee279)
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)
Example fix
# before
example.com {
tls {
ciphers TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256
}
}
example.com {
tls {
ciphers TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384
}
}
# after
example.com {
tls {
ciphers TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384
}
} Defensive patterns
Strategy: validation
Validate before calling
# One ciphers list per hostname across all blocks
for h, lists in group_ciphers_by_host(sites).items():
assert len({tuple(l) for l in lists if l}) <= 1, f'conflicting ciphers for {h}' Prevention
- 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
When it happens
Trigger: 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.
Common situations: 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.
Related errors
- 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 curve
- two policies with same match criteria have conflicting defau
- two policies with same match criteria have conflicting fallb
AI-assisted analysis of caddyserver/caddy@50e54ee279 (2026-08-15).
Data as JSON: /api/errors/bf33c973bd8be0a5.
Report an issue: GitHub.