{"record":{"id":"1313b10bb73857af","repo":"cloudflare/cloudflared","slug":"expected-at-least-2-cloudflare-regions-regions-bu","errorCode":null,"errorMessage":"expected at least 2 Cloudflare Regions regions, but SRV only returned %v","messagePattern":"expected at least 2 Cloudflare Regions regions, but SRV only returned (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"edgediscovery/allregions/regions.go","lineNumber":28,"sourceCode":"// Regions stores Cloudflare edge network IPs, partitioned into two regions.\n// This is NOT thread-safe. Users of this package should use it with a lock.\ntype Regions struct {\n\tregion1 Region\n\tregion2 Region\n}\n\n// ------------------------------------\n// Constructors\n// ------------------------------------\n\n// ResolveEdge resolves the Cloudflare edge, returning all regions discovered.\nfunc ResolveEdge(log *zerolog.Logger, region string, overrideIPVersion ConfigIPVersion) (*Regions, error) {\n\tedgeAddrs, err := EdgeDiscovery(log, RegionalServiceName(region))\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\tif len(edgeAddrs) < 2 {\n\t\treturn nil, fmt.Errorf(\"expected at least 2 Cloudflare Regions regions, but SRV only returned %v\", len(edgeAddrs))\n\t}\n\treturn &Regions{\n\t\tregion1: NewRegion(edgeAddrs[0], overrideIPVersion),\n\t\tregion2: NewRegion(edgeAddrs[1], overrideIPVersion),\n\t}, nil\n}\n\n// StaticEdge creates a list of edge addresses from the list of hostnames.\n// Mainly used for testing connectivity.\nfunc StaticEdge(hostnames []string, log *zerolog.Logger) (*Regions, error) {\n\tresolved := ResolveAddrs(hostnames, log)\n\tif len(resolved) == 0 {\n\t\treturn nil, fmt.Errorf(\"failed to resolve any edge address\")\n\t}\n\treturn NewNoResolve(resolved), nil\n}\n\n// NewNoResolve doesn't resolve the edge. Instead it just uses the given addresses.","sourceCodeStart":10,"sourceCodeEnd":46,"githubUrl":"https://github.com/cloudflare/cloudflared/blob/2253eeeb25a44a713a4b60b8ba1e1b3f377d1a0f/edgediscovery/allregions/regions.go#L10-L46","documentation":"ResolveEdge discovers Cloudflare edge addresses via SRV lookup and builds a Regions object that requires at least two addresses — one for each of the two logical edge regions (region1/region2) used for redundant connections. When EdgeDiscovery returns fewer than 2 addresses, cloudflared cannot construct redundant region connections, so this error is thrown reporting how many addresses the SRV lookup actually returned. The count is embedded in the message, e.g. 'SRV only returned 1'.","triggerScenarios":"Calling ResolveEdge (used when establishing tunnel connections) where EdgeDiscovery(RegionalServiceName(region)) succeeds but returns fewer than 2 EdgeAddr values — e.g. only one SRV target resolved, or repeated SRV targets collapsed to one address, or partial DNS failures dropped addresses.","commonSituations":"Degraded corporate DNS/VPN returning partial answers for Cloudflare SRV records; a region override (--region us) reducing discoverable addresses; network middleboxes stripping AAAA (or A) records so most targets fail resolution; transient DNS outages returning only one usable edge address.","solutions":["Retry — edge discovery is re-run on each connection attempt, and partial DNS answers are usually transient.","Check the resolved count in the message: if it says 1, run 'nslookup -type=SRV <region service name>' yourself to confirm what your resolver returns and fix the resolver/VPN.","Remove the --region restriction if set, so discovery can find addresses across all regions.","Pin edge addresses explicitly with --edge <ip:port> list to bypass SRV-based region discovery entirely."],"exampleFix":"// before\n// cloudflared tunnel --region us run <tunnel>   // SRV only returned 1\n// after — drop the region pin or pin the edge manually:\n// cloudflared tunnel --edge 198.41.192.7:7844,198.41.200.13:7844 run <tunnel>","handlingStrategy":"fallback","validationCode":"func canDiscoverEnoughEdgeAddrs(service string) bool {\n    _, addrs, err := net.LookupSRV(\"\", \"\", service)\n    if err != nil {\n        return false\n    }\n    n := 0\n    for _, srv := range addrs {\n        if ips, err := net.LookupIP(srv.Target); err == nil {\n            n += len(ips)\n        }\n    }\n    return n >= 2\n}","typeGuard":null,"tryCatchPattern":"regions, err := allregions.ResolveEdge(log, region, ipVersion)\nif err != nil {\n    if strings.Contains(err.Error(), \"SRV only returned\") {\n        logger.Warn().Err(err).Msg(\"insufficient edge addresses; falling back to explicit --edge list\")\n        return useStaticEdgeAddrs() // fallback path\n    }\n    return err\n}","preventionTips":["Avoid narrowing discovery with --region unless required; fewer regions means fewer addresses","Verify corporate DNS/VPN returns complete SRV answers for Cloudflare edge domains before rollout","Ensure both A and AAAA resolution works if you rely on a single IP version, or set --edge-ip-version to the family your network supports","Keep a documented --edge fallback address list for degraded-DNS environments"],"tags":["network","dns","srv-record","edge-discovery","redundancy"],"backgroundTag":"empty-result-set","analyzedSha":"2253eeeb25a44a713a4b60b8ba1e1b3f377d1a0f","analyzedAt":"2026-09-06T04:14:33.757Z","contentChangedAt":"2026-09-06T04:14:33.757Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}