XX-net/XX-Net · warning
query_dns_from_xxnet fail status:%d, cost=%f
Error message
query_dns_from_xxnet fail status:%d, cost=%f
What it means
query_dns_from_xxnet() sends a GET to dns.xx-net.org via g.x_tunnel.front_dispatcher.request to resolve a domain; if the returned HTTP status is not 200 (e.g. 404, 502, or a tunnel error code), it logs this warning with the status and elapsed time and returns an empty IP list.
Source
Thrown at code/default/smart_router/local/dns_query.py:109
except Exception as e:
xlog.warn("get ip address e:%r", e)
ips = [b'127.0.0.1']
xlog.debug("local ips: %s", ips)
return ips
def query_dns_from_xxnet(domain, dns_type=None):
if not g.x_tunnel:
return []
t0 = time.time()
content, status, response = g.x_tunnel.front_dispatcher.request(
"GET", "dns.xx-net.org", path="/query?domain=%s" % (utils.to_str(domain)), timeout=5)
t1 = time.time()
if status != 200:
xlog.warn("query_dns_from_xxnet fail status:%d, cost=%f", status, t1 - t0)
return []
if isinstance(content, memoryview):
content = content.tobytes()
content = utils.to_str(content)
try:
rs = json.loads(content)
ips = rs["ip"]
xlog.debug("query_dns_from_xxnet %s cost:%f return:%s", domain, t1 - t0, ips)
#if dns_type == 1:
# ips = [ip for ip in ips if "." in ip]
ips_out = []
for ip_cn in ips:
ip, cn = ip_cn.split("|")
ips_out.append(ip)
return ips_outView on GitHub (pinned to cfa5bc17b6)
Solutions
- Check that the X-Tunnel is connected and working (g.x_tunnel.front_dispatcher is initialized and other requests succeed).
- Retry the call after a short delay — transient upstream failures are common.
- Verify network egress to dns.xx-net.org isn't blocked by a firewall; test from another network.
- Inspect the numeric status in the log: 5xx points to the remote service, 4xx/0 to the tunnel or request path.
Example fix
// before
content, status, response = g.x_tunnel.front_dispatcher.request(
"GET", "dns.xx-net.org", path="/query?domain=%s" % utils.to_str(domain), timeout=5)
if status != 200:
xlog.warn("query_dns_from_xxnet fail status:%d, cost=%f", status, t1 - t0)
return []
// after
for attempt in range(3):
content, status, response = g.x_tunnel.front_dispatcher.request(
"GET", "dns.xx-net.org", path="/query?domain=%s" % utils.to_str(domain), timeout=5)
if status == 200:
break
time.sleep(1 + attempt)
else:
xlog.warn("query_dns_from_xxnet fail after retries")
return [] Defensive patterns
Strategy: retry
Validate before calling
if g.x_tunnel is None or not getattr(g.x_tunnel, 'front_dispatcher', None):
raise RuntimeError('X-Tunnel front dispatcher not ready; DNS query would fail') Try / catch
ips = query_dns_from_xxnet(domain)
if not ips:
# returns [] on non-200 or parse failure; fall back to system DNS
ips = socket.gethostbyname_ex(domain)[2] Prevention
- Ensure the tunnel is connected before invoking remote DNS queries.
- Wrap calls with retry + exponential backoff for transient upstream failures.
- Always provide a fallback resolver path when query_dns_from_xxnet returns [].
- Watch the logged status code to distinguish upstream 5xx from tunnel-level failures.
When it happens
Trigger: Calling query_dns_from_xxnet() when the X-Tunnel front dispatcher can't complete the request: the remote DNS service returns an error status, the tunnel is unhealthy, the target domain is unreachable, or the request exceeds its 5-second timeout path and reports a non-200 status.
Common situations: XX-Net tunnel not connected or front dispatcher uninitialized; dns.xx-net.org backend down or moved; GFW/network interference on the tunnel path; auth/quota issues causing an error status instead of 200; transient upstream 5xx.
Related errors
- query_dns_from_xxnet %s json:%s parse fail:%s
- remove local DNS server %s from upstream
- DNSOverHttpsQuery query fail:%r
- DnsOverHttpsQuery query %s cost:%f fail:%r
- time out
AI-assisted analysis of XX-net/XX-Net@cfa5bc17b6 (2026-08-27).
Data as JSON: /api/errors/9a482d62b3879c74.
Report an issue: GitHub.