{"record":{"id":"79817568cc5908c5","repo":"caddyserver/caddy","slug":"local-address-must-be-a-tcp-address-not-a-udp-add","errorCode":null,"errorMessage":"local_address must be a TCP address, not a UDP address","messagePattern":"local_address must be a TCP address, not a UDP address","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"modules/caddyhttp/reverseproxy/httptransport.go","lineNumber":253,"sourceCode":"\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\tif netaddr.PortRangeSize() > 1 {\n\t\t\treturn nil, fmt.Errorf(\"local_address must be a single address, not a port range\")\n\t\t}\n\t\tswitch netaddr.Network {\n\t\tcase \"tcp\", \"tcp4\", \"tcp6\":\n\t\t\tdialer.LocalAddr, err = net.ResolveTCPAddr(netaddr.Network, netaddr.JoinHostPort(0))\n\t\t\tif err != nil {\n\t\t\t\treturn nil, err\n\t\t\t}\n\t\tcase \"unix\", \"unixgram\", \"unixpacket\":\n\t\t\tdialer.LocalAddr, err = net.ResolveUnixAddr(netaddr.Network, netaddr.JoinHostPort(0))\n\t\t\tif err != nil {\n\t\t\t\treturn nil, err\n\t\t\t}\n\t\tcase \"udp\", \"udp4\", \"udp6\":\n\t\t\treturn nil, fmt.Errorf(\"local_address must be a TCP address, not a UDP address\")\n\t\tdefault:\n\t\t\treturn nil, fmt.Errorf(\"unsupported network\")\n\t\t}\n\t}\n\tif h.Resolver != nil {\n\t\terr := h.Resolver.ParseAddresses()\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\td := &net.Dialer{\n\t\t\tTimeout:       time.Duration(h.DialTimeout),\n\t\t\tFallbackDelay: time.Duration(h.FallbackDelay),\n\t\t}\n\t\tdialer.Resolver = &net.Resolver{\n\t\t\tPreferGo: true,\n\t\t\tDial: func(ctx context.Context, _, _ string) (net.Conn, error) {\n\t\t\t\t//nolint:gosec\n\t\t\t\taddr := h.Resolver.netAddrs[weakrand.IntN(len(h.Resolver.netAddrs))]","sourceCodeStart":235,"sourceCodeEnd":271,"githubUrl":"https://github.com/caddyserver/caddy/blob/50e54ee279aa1e504fe218ca49ab6ae16c100410/modules/caddyhttp/reverseproxy/httptransport.go#L235-L271","documentation":"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.","triggerScenarios":"`transport http { local_address udp://10.0.0.5:0 }` or `local_address udp6/::1` in JSON config.","commonSituations":"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.","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"],"exampleFix":"# before\ntransport http {\n\tlocal_address udp/10.0.0.5\n}\n# after\ntransport http {\n\tlocal_address 10.0.0.5\n}","handlingStrategy":"validation","validationCode":"if strings.HasPrefix(localAddr, \"udp\") {\n\treturn fmt.Errorf(\"local_address: UDP not supported; use tcp\")\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Keep local_address in the tcp family (default)","HTTP/3 upstream dialing does not use this field"],"tags":["reverse-proxy","http-transport","network","validation"],"backgroundTag":null,"analyzedSha":"50e54ee279aa1e504fe218ca49ab6ae16c100410","analyzedAt":"2026-08-15T09:20:21.641Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}