XX-net/XX-Net · warning

DNSOverHttpsQuery query fail:%r

Error message

DNSOverHttpsQuery query fail:%r

What it means

A DNS-over-HTTPS query failed with an unexpected exception inside query_json. The method wraps the whole JSON DoH request/parse cycle in a try/except and logs the exception %r, returning an empty IP list instead of raising. Typical underlying causes are network timeouts, TLS errors, or malformed JSON responses from the DoH server.

Source

Thrown at code/default/smart_router/local/dns_query.py:556

            r = client.request("GET", url, headers={"accept": "application/dns-json"})
            t2 = time.time()
            ips = []
            if not r:
                xlog.warn("DNS server:%s domain:%s fail t:%f", self.server, domain,  t2 - t0)
                return ips

            t = utils.to_str(r.text)

            data = json.loads(t)
            for answer in data["Answer"]:
                ips.append(answer["data"])

            self.connections.append([client, time.time()])

            xlog.debug("DNS server:%s query:%s return %s t:%f", self.server, domain, ips, t2 - t0)
            return ips
        except Exception as e:
            xlog.warn("DNSOverHttpsQuery query fail:%r", e)
            return []

    def query(self, domain, dns_type=1, url=None):
        t0 = time.time()
        try:
            client = self.get_connection()

            if not url:
                url = self.server
            # xlog.debug("DoH use %s", url)

            d = DNSRecord(DNSHeader())
            d.add_question(DNSQuestion(domain, dns_type))
            data = d.pack()

            r = client.request("POST", url, headers={"accept": "application/dns-message",
                                                     "content-type": "application/dns-message"}, body=data)

View on GitHub (pinned to cfa5bc17b6)

Solutions

  1. Check network reachability of the DoH server URL (curl it) and verify it returns application/dns-json responses
  2. Inspect the logged exception %r to identify timeout vs TLS vs parse errors
  3. Retry with a different DoH provider or fall back to plain UDP DNS
  4. Increase client timeout / reuse connections in self.connections pool

Example fix

// before
ips = doh.query_json(domain)
// after
ips = doh.query_json(domain)
if not ips:
    ips = udp_resolver.query(domain)  # fallback resolver
Defensive patterns

Strategy: fallback

Validate before calling

def has_doh_endpoint(url):
    return url.startswith("https://") and "/dns" in url

Try / catch

try:
    ips = doh.query_json(domain)
except Exception:
    ips = []
if not ips:
    ips = fallback_resolver.query(domain)

Prevention

When it happens

Trigger: Calling DNSOverHttpsQuery.query_json() when the HTTPS request to the DoH endpoint raises (connection refused, timeout, SSL verification failure), or when the response body cannot be parsed as the expected JSON DNS answer.

Common situations: DoH server URL misconfigured or unreachable, proxy blocking the DoH endpoint, server returning an HTML error page instead of DNS JSON, or Python 2/3 bytes/str issues when parsing r.text.

Related errors


AI-assisted analysis of XX-net/XX-Net@cfa5bc17b6 (2026-08-27). Data as JSON: /api/errors/881f8a1eb79b8b3c. Report an issue: GitHub.