caddyserver/caddy · error
local_address must be a TCP address, not a UDP address
Error message
local_address must be a TCP address, not a UDP address
What it means
local_address must identify a TCP-family (or unix socket) address because it is fed to net.Dialer.LocalAddr via net.ResolveTCPAddr/ResolveUnixAddr. Explicitly UDP networks (udp, udp4, udp6) are rejected with this message during transport setup.
Source
Thrown at modules/caddyhttp/reverseproxy/httptransport.go:253
if err != nil {
return nil, err
}
if netaddr.PortRangeSize() > 1 {
return nil, fmt.Errorf("local_address must be a single address, not a port range")
}
switch netaddr.Network {
case "tcp", "tcp4", "tcp6":
dialer.LocalAddr, err = net.ResolveTCPAddr(netaddr.Network, netaddr.JoinHostPort(0))
if err != nil {
return nil, err
}
case "unix", "unixgram", "unixpacket":
dialer.LocalAddr, err = net.ResolveUnixAddr(netaddr.Network, netaddr.JoinHostPort(0))
if err != nil {
return nil, err
}
case "udp", "udp4", "udp6":
return nil, fmt.Errorf("local_address must be a TCP address, not a UDP address")
default:
return nil, fmt.Errorf("unsupported network")
}
}
if h.Resolver != nil {
err := h.Resolver.ParseAddresses()
if err != nil {
return nil, err
}
d := &net.Dialer{
Timeout: time.Duration(h.DialTimeout),
FallbackDelay: time.Duration(h.FallbackDelay),
}
dialer.Resolver = &net.Resolver{
PreferGo: true,
Dial: func(ctx context.Context, _, _ string) (net.Conn, error) {
//nolint:gosec
addr := h.Resolver.netAddrs[weakrand.IntN(len(h.Resolver.netAddrs))]View on GitHub (pinned to 50e54ee279)
Solutions
- Remove the udp network prefix: use local_address 10.0.0.5 or tcp/10.0.0.5
- Note that HTTP/3 upstream connections are handled by the h3 transport, not by this dialer's local_address
Example fix
# before
transport http {
local_address udp/10.0.0.5
}
# after
transport http {
local_address 10.0.0.5
} Defensive patterns
Strategy: validation
Validate before calling
if strings.HasPrefix(localAddr, "udp") {
return fmt.Errorf("local_address: UDP not supported; use tcp")
} Prevention
- Keep local_address in the tcp family (default)
- HTTP/3 upstream dialing does not use this field
When it happens
Trigger: `transport http { local_address udp://10.0.0.5:0 }` or `local_address udp6/::1` in JSON config.
Common situations: Confusing the upstream dial address format with the local bind address; infrastructure docs that describe the interface as UDP (e.g. QUIC/HTTP3 front-end) leading the operator to try a UDP local_address for the outbound proxy connection.
Related errors
- local_address must be a single address, not a port range
- unsupported network
- unsupported HTTP version: %s, supported version: %s
- unsupported network type: %s
- invalid IP address: '%s': %v
AI-assisted analysis of caddyserver/caddy@50e54ee279 (2026-08-15).
Data as JSON: /api/errors/79817568cc5908c5.
Report an issue: GitHub.