{"record":{"id":"d1abba7a288f832b","repo":"XX-net/XX-Net","slug":"dnsoverhttpsquery-query-s-cost-f-fail-r","errorCode":null,"errorMessage":"DnsOverHttpsQuery query %s cost:%f fail:%r","messagePattern":"DnsOverHttpsQuery query (.+?) cost:(.+?) fail:%r","errorType":"console","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"code/default/smart_router/local/dns_query.py","lineNumber":601,"sourceCode":"            self.connections.append([client, time.time()])\n\n            for r in p.rr:\n                ip = utils.to_bytes(str(r.rdata))\n                if not utils.check_ip_valid(ip):\n                    if ip == domain:\n                        continue\n\n                    ip_ips = self.query(ip, dns_type)\n                    ips += ip_ips\n                else:\n                    ips.append(ip)\n\n            xlog.debug(\"DNS %s %s return %s t:%f\", self.protocol, domain, ips, t2 - t0)\n            return ips\n        except Exception as e:\n            t1 = time.time()\n            t = t1 - t0\n            xlog.warn(\"DnsOverHttpsQuery query %s cost:%f fail:%r\", domain, t, e)\n            return []\n\n\nclass ParallelQuery():\n    def query_worker(self, task, function):\n        ips = function(task.domain, task.dns_type)\n        if len(ips):\n            g.domain_cache.set_ips(task.domain, ips, task.dns_type)\n            task.put(ips)\n\n    def query(self, domain, dns_type, funcs):\n        task = Queue()\n        task.domain = domain\n        task.dns_type = dns_type\n\n        for func in funcs:\n            threading.Thread(target=self.query_worker, args=(task, func), name=\"ParalleQuery_%s\" % domain).start()\n","sourceCodeStart":583,"sourceCodeEnd":619,"githubUrl":"https://github.com/XX-net/XX-Net/blob/cfa5bc17b67676e467f37ec50766127e0ab5f0aa/code/default/smart_router/local/dns_query.py#L583-L619","documentation":"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.","triggerScenarios":"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.","commonSituations":"DoH endpoint returns a captive-portal/HTML page, TLS interception by middleboxes, transient network failures, malformed DNS responses.","solutions":["Check the logged exception: DNSRecord.parse errors mean the body is not a DNS message — verify the URL","curl the DoH URL with a raw wire-format request to confirm it returns application/dns-message","Retry with a different DoH provider or protocol","Add a UDP DNS fallback in the resolver chain"],"exampleFix":null,"handlingStrategy":"fallback","validationCode":null,"typeGuard":null,"tryCatchPattern":"try:\n    ips = doh.query(domain)\nexcept Exception:\n    ips = []  # method already returns [] and logs\nif not ips:\n    ips = secondary_resolver.query(domain)","preventionTips":["Chain resolvers (DoH then UDP) so one failure doesn't break resolution","Test DoH endpoints with raw curl before deploying","Log and alert on repeated failures per endpoint"],"tags":["dns","doh","parse-error","network"],"backgroundTag":"dns-resolution-failed","analyzedSha":"cfa5bc17b67676e467f37ec50766127e0ab5f0aa","analyzedAt":"2026-08-27T19:28:28.225Z","schemaVersion":2},"datasetVersion":"2026-08-28T00:17:15.603Z"}