{"record":{"id":"d97cf4d3594d8a3d","repo":"caddyserver/caddy","slug":"resolver-address-must-have-exactly-one-address-ca-d97cf4","errorCode":null,"errorMessage":"resolver address must have exactly one address; cannot call %v","messagePattern":"resolver address must have exactly one address; cannot call (.+?)","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"modules/caddypki/acmeserver/acmeserver.go","lineNumber":326,"sourceCode":"\t// If no local resolvers are configured, check for global resolvers from TLS app\n\tresolversToUse := ash.Resolvers\n\tif len(resolversToUse) == 0 {\n\t\ttlsAppIface, err := ash.ctx.App(\"tls\")\n\t\tif err == nil {\n\t\t\ttlsApp := tlsAppIface.(*caddytls.TLS)\n\t\t\tif len(tlsApp.Resolvers) > 0 {\n\t\t\t\tresolversToUse = tlsApp.Resolvers\n\t\t\t}\n\t\t}\n\t}\n\n\tfor _, v := range resolversToUse {\n\t\taddr, err := caddy.ParseNetworkAddressWithDefaults(v, \"udp\", 53)\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\tif addr.PortRangeSize() != 1 {\n\t\t\treturn nil, fmt.Errorf(\"resolver address must have exactly one address; cannot call %v\", addr)\n\t\t}\n\t\tash.resolvers = append(ash.resolvers, addr)\n\t}\n\n\tvar resolver *net.Resolver\n\tif len(ash.resolvers) != 0 {\n\t\tdialer := &net.Dialer{\n\t\t\tTimeout: 2 * time.Second,\n\t\t}\n\t\tresolver = &net.Resolver{\n\t\t\tPreferGo: true,\n\t\t\tDial: func(ctx context.Context, network, address string) (net.Conn, error) {\n\t\t\t\t//nolint:gosec\n\t\t\t\taddr := ash.resolvers[weakrand.IntN(len(ash.resolvers))]\n\t\t\t\treturn dialer.DialContext(ctx, addr.Network, addr.JoinHostPort(0))\n\t\t\t},\n\t\t}\n\t} else {","sourceCodeStart":308,"sourceCodeEnd":344,"githubUrl":"https://github.com/caddyserver/caddy/blob/50e54ee279aa1e504fe218ca49ab6ae16c100410/modules/caddypki/acmeserver/acmeserver.go#L308-L344","documentation":"Thrown while building the ACME server's DNS resolver list: each configured resolver address, after ParseNetworkAddressWithDefaults(v, \"udp\", 53), must denote exactly one host:port — i.e. PortRangeSize() == 1. A port range (e.g. `:53-54`), a multi-address form, or a network address expanding to more than one port is rejected. Both tls app resolvers and any default resolvers funnel through this loop.","triggerScenarios":"Configuring `resolvers` (in the tls app or a DNS-provider context) with a value like `1.1.1.1:53-55`, `dns://1.1.1.1,*`, or an address string that Caddy's network-address parser expands into a port range. The loop over resolversToUse computes PortRangeSize() and returns this error instead of the resolver list.","commonSituations":"Copy-pasting a resolver list from a DNS load-balancing config where ranges are legal; accidentally using Caddy's listener-style address syntax (which supports port ranges for bind addresses) in a DNS resolver field; trailing comma producing an odd parsed address.","solutions":["Use a single host with one port per resolver entry: `resolvers 1.1.1.1 8.8.8.8` (port defaults to 53/udp)","Remove any port-range syntax (`-`) and multi-host expansion from resolver values","Add one resolver address per list item rather than compressing into one token","Validate with `caddy validate --config` before deploy"],"exampleFix":"# before\n{\n  acme_server\n}\ntls {\n  dns cloudflare {env.CF_TOKEN}\n  resolvers 1.1.1.1:53-54\n}\n\n# after\ntls {\n  dns cloudflare {env.CF_TOKEN}\n  resolvers 1.1.1.1 8.8.8.8\n}","handlingStrategy":"validation","validationCode":"// Validate resolver addresses exactly as the server does:\nfor _, v := range resolvers {\n    addr, err := caddy.ParseNetworkAddressWithDefaults(v, \"udp\", 53)\n    if err != nil { return err }\n    if addr.PortRangeSize() != 1 {\n        return fmt.Errorf(\"resolver %q expands to %d ports\", v, addr.PortRangeSize())\n    }\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["One host per resolver entry, no port ranges","Prefer bare IPs or hostnames without ports (defaults to udp/53)","CI-validate the tls app config after resolver changes"],"tags":["pki","acme","dns","resolvers","validation"],"backgroundTag":null,"analyzedSha":"50e54ee279aa1e504fe218ca49ab6ae16c100410","analyzedAt":"2026-08-15T09:20:21.641Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}