{"record":{"id":"9a482d62b3879c74","repo":"XX-net/XX-Net","slug":"query-dns-from-xxnet-fail-status-d-cost-f","errorCode":null,"errorMessage":"query_dns_from_xxnet fail status:%d, cost=%f","messagePattern":"query_dns_from_xxnet fail status:(.+?), cost=(.+?)","errorType":"console","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"code/default/smart_router/local/dns_query.py","lineNumber":109,"sourceCode":"        except Exception as e:\n            xlog.warn(\"get ip address e:%r\", e)\n            ips = [b'127.0.0.1']\n\n    xlog.debug(\"local ips: %s\", ips)\n    return ips\n\n\ndef query_dns_from_xxnet(domain, dns_type=None):\n    if not g.x_tunnel:\n        return []\n\n    t0 = time.time()\n    content, status, response = g.x_tunnel.front_dispatcher.request(\n        \"GET\", \"dns.xx-net.org\", path=\"/query?domain=%s\" % (utils.to_str(domain)), timeout=5)\n    t1 = time.time()\n\n    if status != 200:\n        xlog.warn(\"query_dns_from_xxnet fail status:%d, cost=%f\", status, t1 - t0)\n        return []\n\n    if isinstance(content, memoryview):\n        content = content.tobytes()\n\n    content = utils.to_str(content)\n\n    try:\n        rs = json.loads(content)\n        ips = rs[\"ip\"]\n        xlog.debug(\"query_dns_from_xxnet %s cost:%f return:%s\", domain, t1 - t0, ips)\n        #if dns_type == 1:\n        #    ips = [ip for ip in ips if \".\" in ip]\n        ips_out = []\n        for ip_cn in ips:\n            ip, cn = ip_cn.split(\"|\")\n            ips_out.append(ip)\n        return ips_out","sourceCodeStart":91,"sourceCodeEnd":127,"githubUrl":"https://github.com/XX-net/XX-Net/blob/cfa5bc17b67676e467f37ec50766127e0ab5f0aa/code/default/smart_router/local/dns_query.py#L91-L127","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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."],"exampleFix":"// before\ncontent, status, response = g.x_tunnel.front_dispatcher.request(\n    \"GET\", \"dns.xx-net.org\", path=\"/query?domain=%s\" % utils.to_str(domain), timeout=5)\nif status != 200:\n    xlog.warn(\"query_dns_from_xxnet fail status:%d, cost=%f\", status, t1 - t0)\n    return []\n\n// after\nfor attempt in range(3):\n    content, status, response = g.x_tunnel.front_dispatcher.request(\n        \"GET\", \"dns.xx-net.org\", path=\"/query?domain=%s\" % utils.to_str(domain), timeout=5)\n    if status == 200:\n        break\n    time.sleep(1 + attempt)\nelse:\n    xlog.warn(\"query_dns_from_xxnet fail after retries\")\n    return []","handlingStrategy":"retry","validationCode":"if g.x_tunnel is None or not getattr(g.x_tunnel, 'front_dispatcher', None):\n    raise RuntimeError('X-Tunnel front dispatcher not ready; DNS query would fail')","typeGuard":null,"tryCatchPattern":"ips = query_dns_from_xxnet(domain)\nif not ips:\n    # returns [] on non-200 or parse failure; fall back to system DNS\n    ips = socket.gethostbyname_ex(domain)[2]","preventionTips":["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."],"tags":["dns","network","xx-tunnel","http-status","smart-router"],"backgroundTag":"upstream-http-request-failed","analyzedSha":"cfa5bc17b67676e467f37ec50766127e0ab5f0aa","analyzedAt":"2026-08-27T19:28:28.225Z","schemaVersion":2},"datasetVersion":"2026-08-28T00:17:15.603Z"}