{"record":{"id":"180aefe066d3fb54","repo":"stamparm/maltrail","slug":"empty-response-from-s","errorCode":null,"errorMessage":"empty response from '%s'","messagePattern":"empty response from '(.+?)'","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"core/update.py","lineNumber":976,"sourceCode":"        if not os.path.isdir(USERS_DIR):\n            os.makedirs(USERS_DIR, 0o755)\n    except Exception as ex:\n        sys.exit(\"[!] something went wrong during creation of directory '%s' ('%s')\" % (USERS_DIR, ex))\n\n    _chown(USERS_DIR)\n\n    if not (force or not os.path.isfile(GEO_IP2CC_FILE) or (time.time() - os.stat(GEO_IP2CC_FILE).st_mtime) >= FRESH_GEO_DELTA_DAYS * 24 * 3600):\n        _chown(GEO_IP2CC_FILE)\n        return\n\n    print(\"[i] updating geolocation (IP->country) database...\")\n\n    v4, v6 = [], []\n    try:\n        for url in RIR_DELEGATED_URLS:\n            content = retrieve_content(url)\n            if not content:\n                raise Exception(\"empty response from '%s'\" % url)\n            if isinstance(content, bytes):\n                content = content.decode(\"latin-1\", \"ignore\")\n            for line in content.splitlines():\n                parts = line.split('|')\n                if len(parts) < 7 or parts[2] not in (\"ipv4\", \"ipv6\") or parts[6] not in (\"allocated\", \"assigned\"):\n                    continue\n                cc = parts[1]\n                if len(cc) != 2 or not cc.isalpha():\n                    continue\n                try:\n                    if parts[2] == \"ipv4\":\n                        start = addr_to_int(parts[3]); v4.append((start, start + int(parts[4]) - 1, cc.upper()))\n                    else:  # ipv6: parts[4] is the prefix length\n                        start = _ip6_to_int(parts[3]); v6.append((start, start + (1 << (128 - int(parts[4]))) - 1, cc.upper()))\n                except Exception:\n                    continue\n    except Exception as ex:\n        print(\"[x] something went wrong during retrieval of RIR delegation stats ('%s')\" % ex)","sourceCodeStart":958,"sourceCodeEnd":994,"githubUrl":"https://github.com/stamparm/maltrail/blob/77cfb06d7606506d101bbcec0786c77166c4255e/core/update.py#L958-L994","documentation":"During the geo-IP database update, update_geo() downloads each RIR delegated-stats file listed in RIR_DELEGATED_URLS via retrieve_content(). If a URL returns empty content (no data), it raises \"empty response from '%s'\" naming the failing URL, because an empty delegated file cannot be parsed into geo ranges.","triggerScenarios":"retrieve_content(url) returned ''/None for one of the RIR_DELEGATED_URLS endpoints — server returned an empty body, a redirect/proxy stripped the payload, a captive portal or WAF blocked the request, or a network layer returned success with zero bytes.","commonSituations":"Running updates behind corporate proxies/firewalls that return empty responses; RIR servers (RIPE/ARIN/APNIC/LACNIC/AFRINIC) temporarily unavailable or rate-limiting; TLS interception appliances swallowing bodies; intermittent network failures on scheduled update_timer runs or at startup via main.","solutions":["Re-run the update later — RIR endpoints occasionally serve transient empty responses; add retry with backoff around retrieve_content for each URL.","Check network egress: verify the failing URL loads from the host (curl -sIL <url>) and that no proxy, captive portal, or WAF strips the body.","Review retrieve_content for silent error swallowing (exceptions converted to '') and make it raise the underlying HTTP/connection error so the failure is diagnosable.","Run the update with outbound HTTPS access and a current CA bundle; pin/verify the RIR URLs are still valid (RIRs occasionally migrate delegated-file locations).","Optionally fail soft: log the specific RIR and continue with the last successfully updated database instead of aborting the whole update."],"exampleFix":"# before\ncontent = retrieve_content(url)\nif not content:\n    raise Exception(\"empty response from '%s'\" % url)\n\n# after\ncontent = None\nfor attempt in range(3):\n    content = retrieve_content(url)\n    if content:\n        break\n    time.sleep(2 ** attempt)\nif not content:\n    raise Exception(\"empty response from '%s'\" % url)","handlingStrategy":"retry","validationCode":"content = retrieve_content(url)\nif content is None or len(content) == 0:\n    # fail fast before update_geo's internal raise; retry or skip this RIR\n    retry_download(url)","typeGuard":"def is_nonempty_str(s):\n    return isinstance(s, (str, bytes)) and len(s) > 0","tryCatchPattern":"try:\n    update_geo()\nexcept Exception as e:\n    if str(e).startswith(\"empty response from\"):\n        log.warning(\"RIR endpoint returned empty body: %s — retrying later\", e)\n    else:\n        raise","preventionTips":["Add per-URL retry with exponential backoff around retrieve_content in scheduled update runs.","Verify proxy/firewall/TLS-interception setups allow full HTTPS bodies from RIR delegated-stats endpoints.","Monitor update_timer logs for repeated empty-response failures to catch egress problems early.","Keep the last successfully downloaded database so a failed update degrades gracefully instead of leaving no geo data."],"tags":["network","http","empty-response","geoip-update"],"backgroundTag":"empty-response-body","analyzedSha":"77cfb06d7606506d101bbcec0786c77166c4255e","analyzedAt":"2026-09-13T03:50:16.010Z","contentChangedAt":"2026-09-13T03:50:16.010Z","schemaVersion":2},"datasetVersion":"2026-09-16T09:17:16.951Z"}