caddyserver/caddy · error
server listening on %v is configured for HTTP and cannot nat
Error message
server listening on %v is configured for HTTP and cannot natively multiplex HTTP and HTTPS: %s
What it means
Mirror of error 122 from the HTTPS side: the server was already classified as HTTPS (a prior address was https), and a subsequent address resolves to HTTP (`http://` scheme or the configured http_port). One listener cannot serve both protocols, so adaptation fails.
Source
Thrown at caddyconfig/httpcaddyfile/httptype.go:1168
if httpOrHTTPS == "HTTPS" {
errMsg := fmt.Errorf("server listening on %v is configured for HTTPS and cannot natively multiplex HTTP and HTTPS: %s",
srv.Listen, addr.Original)
if addr.Scheme == "" && addr.Host == "" {
errMsg = fmt.Errorf("%s (try specifying https:// in the address)", errMsg)
}
return errMsg
}
if len(srv.TLSConnPolicies) > 0 {
// any connection policies created for an HTTP server
// is a logical conflict, as it would enable HTTPS
return fmt.Errorf("server listening on %v is HTTP, but attempts to configure TLS connection policies", srv.Listen)
}
httpOrHTTPS = "HTTP"
return nil
}
checkAndSetHTTPS := func(addr Address) error {
if httpOrHTTPS == "HTTP" {
return fmt.Errorf("server listening on %v is configured for HTTP and cannot natively multiplex HTTP and HTTPS: %s",
srv.Listen, addr.Original)
}
httpOrHTTPS = "HTTPS"
return nil
}
for _, sblock := range serverBlocks {
for _, addr := range sblock.parsedKeys {
if addr.Scheme == "http" || addr.Port == httpPort {
if err := checkAndSetHTTP(addr); err != nil {
return err
}
} else if addr.Scheme == "https" || addr.Port == httpsPort || len(srv.TLSConnPolicies) > 0 {
if err := checkAndSetHTTPS(addr); err != nil {
return err
}
} else if addr.Host == "" {
if err := checkAndSetHTTP(addr); err != nil {View on GitHub (pinned to 50e54ee279)
Solutions
- Move the http:// site to the HTTP port (default :80)
- Change the http:// address to https://
- Separate the sites with explicit `bind` or distinct ports so they form different servers
Example fix
# before
https://example.com {
respond "tls"
}
http://api.example.com:443 {
respond "api"
}
# after
https://example.com {
respond "tls"
}
http://api.example.com:80 {
respond "api"
} Defensive patterns
Strategy: validation
Validate before calling
# Mirror of 122: one scheme per listener group
for group in group_addresses_by_listener(all_keys):
schemes = {infer_scheme(a) for a in group}
assert len(schemes) == 1 Prevention
- Give http:// sites the dedicated HTTP port
- Do not use http:// on 443 to disable auto-HTTPS; use auto_https off instead
- Validate with caddy adapt before reload
When it happens
Trigger: A server whose first site key is `https://example.com` followed by another key/block on the same listener with `http://` scheme or a port equal to `http_port` — e.g. `https://example.com:80` after `https://example.com`, or `http://foo.example.com` sharing the https port via matching listener addresses.
Common situations: Forcing `http://` on the HTTPS port to dodge automatic HTTPS, or merging two previously separate site files into one server where one used TLS and one did not.
Related errors
- server listening on %v is configured for HTTPS and cannot na
- %s (try specifying https:// in the address)
- server listening on %v is HTTP, but attempts to configure TL
- request path is missing object ID
- malformed object path
AI-assisted analysis of caddyserver/caddy@50e54ee279 (2026-08-15).
Data as JSON: /api/errors/d30ee22be0c17dae.
Report an issue: GitHub.