caddyserver/caddy · error
network '%s' cannot handle HTTP/1 or HTTP/2 connections
Error message
network '%s' cannot handle HTTP/1 or HTTP/2 connections
What it means
After successfully creating a socket for an HTTP-capable protocol set, Caddy asserts the returned object is a net.Listener (stream socket). Non-stream networks (e.g. unixgram, or packet-oriented networks) cannot serve HTTP/1 or HTTP/2, so Start rejects them with the network name from the listen address.
Source
Thrown at modules/caddyhttp/app.go:574
// enable TLS if there is a policy and if this is not the HTTP port
useTLS := len(srv.TLSConnPolicies) > 0 && int(listenAddr.StartPort+portOffset) != app.httpPort()
if h1ok || h2ok && useTLS || h2cok {
// create the listener for this socket
lnAny, err := listenAddr.Listen(app.ctx, portOffset, net.ListenConfig{
KeepAliveConfig: net.KeepAliveConfig{
Enable: srv.KeepAliveInterval >= 0,
Interval: time.Duration(srv.KeepAliveInterval),
Idle: time.Duration(srv.KeepAliveIdle),
Count: srv.KeepAliveCount,
},
})
if err != nil {
return fmt.Errorf("listening on %s: %v", listenAddr.At(portOffset), err)
}
ln, ok := lnAny.(net.Listener)
if !ok {
return fmt.Errorf("network '%s' cannot handle HTTP/1 or HTTP/2 connections", listenAddr.Network)
}
// wrap listener before TLS (up to the TLS placeholder wrapper)
var lnWrapperIdx int
for i, lnWrapper := range srv.listenerWrappers {
if _, ok := lnWrapper.(*tlsPlaceholderWrapper); ok {
lnWrapperIdx = i + 1 // mark the next wrapper's spot
break
}
ln = lnWrapper.WrapListener(ln)
}
if useTLS {
// create TLS listener - this enables and terminates TLS
ln = tls.NewListener(ln, tlsCfg)
}
// finish wrapping listener where we left off before TLSView on GitHub (pinned to 50e54ee279)
Solutions
- Use a stream network for HTTP servers: plain host:port (tcp) or unix/<path> ("unix//tmp/caddy.sock")
- Reserve udp/GRAM networks for the automatic HTTP/3 handling, not explicit listen entries
Example fix
// before "listen": ["unixgram//run/caddy.sock"] // after "listen": ["unix//run/caddy.sock"]
Defensive patterns
Strategy: validation
Validate before calling
for _, a := range srvCfg.Listen {
na, err := caddy.ParseNetworkAddress(a)
if err != nil { return err }
switch na.Network {
case "", "tcp", "tcp4", "tcp6", "unix":
default:
if !strings.Contains(na.Network, "gram") && na.Network != "udp" { /* ... */ }
return fmt.Errorf("network %q cannot serve HTTP/1-2; use tcp/unix", na.Network)
}
} Prevention
- Use tcp (default) or unix networks for HTTP servers
- Leave udp/QUIC to Caddy's automatic HTTP/3 handling on the same tcp listener
When it happens
Trigger: Using a datagram/packet network in listen for a server whose protocols include h1/h2/h2c, e.g. "unixgram//path/to/socket" or ip4 networks; only quic-capable networks legitimately use packet conns via the HTTP/3 path.
Common situations: Trying to serve HTTP over a unixgram socket copied from a UDP example; mistaking the l4 module's network syntax for http server listen syntax.
Related errors
- listening on %s: %v
- %s: parsing listen address '%s': %v
- starting HTTP/3 QUIC listener: %v
- %s app module: start: %v
- starting caddy administration endpoint: %v
AI-assisted analysis of caddyserver/caddy@50e54ee279 (2026-08-15).
Data as JSON: /api/errors/6456940b9bd1cd21.
Report an issue: GitHub.