{"record":{"id":"9d31ea598387461b","repo":"XX-net/XX-Net","slug":"query-dns-from-xxnet-s-json-s-parse-fail-s","errorCode":null,"errorMessage":"query_dns_from_xxnet %s json:%s parse fail:%s","messagePattern":"query_dns_from_xxnet (.+?) json:(.+?) parse fail:(.+?)","errorType":"console","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"code/default/smart_router/local/dns_query.py","lineNumber":129,"sourceCode":"\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\n    except Exception as e:\n        xlog.warn(\"query_dns_from_xxnet %s json:%s parse fail:%s\", domain, content, e)\n        return []\n\n\nclass LocalDnsQuery():\n    def __init__(self, timeout=3):\n        self.timeout = timeout\n        self.waiters = lru_cache.LruCache(100)\n        self.dns_server = self.get_local_dns_server()\n\n        self.sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)\n        self.sock6 = socket.socket(socket.AF_INET6, socket.SOCK_DGRAM)\n        self.sock.settimeout(1)\n        self.sock6.settimeout(1)\n\n        self.running = True\n        self.th = threading.Thread(target=self.dns_recv_worker, args=(self.sock,), name=\"dns_ipv4_receiver\")\n        self.th.start()\n","sourceCodeStart":111,"sourceCodeEnd":147,"githubUrl":"https://github.com/XX-net/XX-Net/blob/cfa5bc17b67676e467f37ec50766127e0ab5f0aa/code/default/smart_router/local/dns_query.py#L111-L147","documentation":"query_dns_from_xxnet() got a 200 response but failed while parsing: it either couldn't json-decode the body or couldn't split the 'ip|cn' entries in the returned list. The warning includes the domain, the raw content, and the parse exception, then returns an empty IP list.","triggerScenarios":"Calling query_dns_from_xxnet() when the remote DNS service returns an unexpected body — non-JSON text (error page, HTML), JSON without the expected list structure, or entries not containing the '|' separator, causing ValueError/KeyError/TypeError inside the parse block.","commonSituations":"The remote dns.xx-net.org API changed format (e.g. dropped the ip|cn pairing); a proxy/captive portal injecting an HTML page; truncated response body; encoding issues where utils.to_str produced garbled text.","solutions":["Look at the 'json:' field in the log line to see the actual body — that immediately reveals whether it's an HTML interstitial, an API error message, or a format change.","Verify you're on a current XX-Net version whose parser matches the current dns.xx-net.org response format.","If a captive portal/proxy is intercepting, fix connectivity so the tunnel delivers the real payload.","Report a format-change upstream and patch the parser to tolerate missing '|' (e.g. ip_cn.split('|')[0])."],"exampleFix":"// before\nfor ip_cn in ips:\n    ip, cn = ip_cn.split(\"|\")\n    ips_out.append(ip)\n\n// after\nfor ip_cn in ips:\n    ip = ip_cn.split(\"|\")[0]\n    if ip:\n        ips_out.append(ip)","handlingStrategy":"try-catch","validationCode":"# sanity-check contract before relying on the result\nips = query_dns_from_xxnet(domain)\nassert isinstance(ips, list) and all(b'.' in ip or ':' in ip for ip in ips), 'bad DNS payload'","typeGuard":null,"tryCatchPattern":"try:\n    ips = query_dns_from_xxnet(domain)\nexcept Exception:\n    ips = []\nif not ips:\n    ips = socket.gethostbyname_ex(domain)[2]  # fallback to system resolution","preventionTips":["Treat a 200-but-unparseable body as an API contract change; log and fall back to system DNS.","Make parsing defensive: split('|')[0], tolerate missing fields.","Pin the XX-Net version to one matching the dns.xx-net.org response format; test after upgrading."],"tags":["dns","json","parsing","api-contract","smart-router"],"backgroundTag":"json-response-parse-failure","analyzedSha":"cfa5bc17b67676e467f37ec50766127e0ab5f0aa","analyzedAt":"2026-08-27T19:28:28.225Z","schemaVersion":2},"datasetVersion":"2026-08-28T00:17:15.603Z"}