caddyserver/caddy · error

server listening on %v is configured for HTTPS and cannot na

Error message

server listening on %v is configured for HTTPS and cannot natively multiplex HTTP and HTTPS: %s

What it means

The same Caddy server (same listener set) received both HTTP and HTTPS site addresses. Go's net/http cannot multiplex cleartext and TLS on one listener, so the adapter refuses to build a server that mixes `http://` and `https://` addresses on the same socket.

Source

Thrown at caddyconfig/httpcaddyfile/httptype.go:1151

		return nil, false
	}
	return sni, true
}

func detectConflictingSchemes(srv *caddyhttp.Server, serverBlocks []serverBlock, options map[string]any) error {
	httpPort := strconv.Itoa(caddyhttp.DefaultHTTPPort)
	if hp, ok := options["http_port"].(int); ok {
		httpPort = strconv.Itoa(hp)
	}
	httpsPort := strconv.Itoa(caddyhttp.DefaultHTTPSPort)
	if hsp, ok := options["https_port"].(int); ok {
		httpsPort = strconv.Itoa(hsp)
	}

	var httpOrHTTPS string
	checkAndSetHTTP := func(addr Address) error {
		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)

View on GitHub (pinned to 50e54ee279)

Solutions

  1. Give the HTTP site its own port (default :80) and let HTTPS stay on :443
  2. Remove the `http://` scheme from the address if HTTPS was intended on that port
  3. Use distinct `bind` addresses so they do not land in the same server
  4. Enable `auto_https disable_redirects` if you were only trying to suppress the HTTP redirect

Example fix

# before
http://example.com:443 {
  respond "plain" 
}
https://example.com:443 {
  respond "tls"
}
# after
http://example.com:80 {
  respond "plain"
}
https://example.com {
  respond "tls"
}
Defensive patterns

Strategy: validation

Validate before calling

# Before adapting, ensure no listener mixes schemes:
# group addresses by host:port; fail if both http and https appear
for group in group_addresses_by_listener(keys):
    schemes = {a.scheme or infer(a.port) for a in group}
    assert not ({'http','https'} <= schemes), f"mixed protocols on {group}"

Prevention

When it happens

Trigger: Two site blocks (or one block) whose keys resolve to the same listen port where one key is `http://example.com` (or matches the configured `http_port`) and another is `https://example.com` or has scheme https on the same port — e.g. `http://example.com` and `https://example.com` both defaulting to ports that share a listener, or explicit `http://example.com:443` next to `https://example.com:443`.

Common situations: Trying to serve both a redirect target and TLS site on one port, mixing `http://` and bare hostnames that default to HTTPS on the same explicit port, or copying a redirect block that reuses the HTTPS port with an http:// scheme.

Related errors


AI-assisted analysis of caddyserver/caddy@50e54ee279 (2026-08-15). Data as JSON: /api/errors/32579db1f0618d36. Report an issue: GitHub.