XX-net/XX-Net · warning

DnsOverHttpsQuery query %s cost:%f fail:%r

Error message

DnsOverHttpsQuery query %s cost:%f fail:%r

What it means

The wire-format DNS-over-HTTPS query() caught an unexpected exception (parse failure, network error, timeout) and logged the domain, cost and exception before returning []. This is the catch-all safety net for the DoH query path.

Source

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

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

            for r in p.rr:
                ip = utils.to_bytes(str(r.rdata))
                if not utils.check_ip_valid(ip):
                    if ip == domain:
                        continue

                    ip_ips = self.query(ip, dns_type)
                    ips += ip_ips
                else:
                    ips.append(ip)

            xlog.debug("DNS %s %s return %s t:%f", self.protocol, domain, ips, t2 - t0)
            return ips
        except Exception as e:
            t1 = time.time()
            t = t1 - t0
            xlog.warn("DnsOverHttpsQuery query %s cost:%f fail:%r", domain, t, e)
            return []


class ParallelQuery():
    def query_worker(self, task, function):
        ips = function(task.domain, task.dns_type)
        if len(ips):
            g.domain_cache.set_ips(task.domain, ips, task.dns_type)
            task.put(ips)

    def query(self, domain, dns_type, funcs):
        task = Queue()
        task.domain = domain
        task.dns_type = dns_type

        for func in funcs:
            threading.Thread(target=self.query_worker, args=(task, func), name="ParalleQuery_%s" % domain).start()

View on GitHub (pinned to cfa5bc17b6)

Solutions

  1. Check the logged exception: DNSRecord.parse errors mean the body is not a DNS message — verify the URL
  2. curl the DoH URL with a raw wire-format request to confirm it returns application/dns-message
  3. Retry with a different DoH provider or protocol
  4. Add a UDP DNS fallback in the resolver chain
Defensive patterns

Strategy: fallback

Try / catch

try:
    ips = doh.query(domain)
except Exception:
    ips = []  # method already returns [] and logs
if not ips:
    ips = secondary_resolver.query(domain)

Prevention

When it happens

Trigger: Calling DNSOverHttpsQuery.query() when DNSRecord.parse of the response raises (non-DNS body like an HTML error page), when request() throws, or on any unexpected exception during the query.

Common situations: DoH endpoint returns a captive-portal/HTML page, TLS interception by middleboxes, transient network failures, malformed DNS responses.

Related errors


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