{"record":{"id":"c8096801899392d9","repo":"XTLS/Xray-core","slug":"empty-response-body","errorCode":null,"errorMessage":"empty response body","messagePattern":"empty response body","errorType":"console","errorClass":"errors.Error","httpStatus":null,"severity":"error","filePath":"app/geodata/download.go","lineNumber":221,"sourceCode":"\t\tclient = d.httpClient\n\t}\n\tresp, err := client.Do(req)\n\tif err != nil {\n\t\treturn err\n\t}\n\tdefer resp.Body.Close()\n\n\tif resp.StatusCode < http.StatusOK || resp.StatusCode >= http.StatusMultipleChoices {\n\t\tio.Copy(io.Discard, resp.Body)\n\t\treturn errors.New(\"unexpected status code: \", resp.StatusCode)\n\t}\n\n\tn, err := io.Copy(writer, resp.Body)\n\tif err != nil {\n\t\treturn err\n\t}\n\tif n == 0 {\n\t\treturn errors.New(\"empty response body\")\n\t}\n\treturn nil\n}\n\nfunc clean(assets []stage) {\n\tfor _, asset := range assets {\n\t\tif asset.temp != \"\" {\n\t\t\tos.Remove(asset.temp)\n\t\t}\n\t}\n}\n\ntype tx struct {\n\tswaps []swap\n}\n\ntype swap struct {\n\ttarget      string","sourceCodeStart":203,"sourceCodeEnd":239,"githubUrl":"https://github.com/XTLS/Xray-core/blob/7d214f8b094f75322fa3990f8aadad1c912f24f5/app/geodata/download.go#L203-L239","documentation":"Returned by downloadOne when the HTTP response was successful (2xx) but io.Copy transferred 0 bytes from the body to the staged temp file. An empty geodata file cannot be a valid protobuf/-dat payload, so it is rejected rather than written to disk.","triggerScenarios":"A mirror returning 200 with an empty body (or a body that closes immediately) for a geodata asset; Content-Length: 0 responses from a broken CDN edge.","commonSituations":"Corrupt/misconfigured mirror; truncated uploads by the file host; anti-bot endpoints returning 200 with empty content.","solutions":["curl the asset URL and check the downloaded size matches a real geosite/geoip file (MBs, not 0)","Switch to the official mirror","Retry — empty responses from CDN edges are often transient"],"exampleFix":null,"handlingStrategy":"validation","validationCode":"// After download (if you wrap it), sanity-check the file size:\nfi, err := os.Stat(stagedFile)\nif err == nil && fi.Size() == 0 {\n    return errors.New(\"mirror returned empty geodata file; discarding\")\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Prefer reputable mirrors that serve full-size files","Keep known-good geodata files on disk so empty downloads never take effect","The downloader already stages to temp files — never bypass that staging"],"tags":["network","geodata","empty-response","download"],"backgroundTag":null,"analyzedSha":"7d214f8b094f75322fa3990f8aadad1c912f24f5","analyzedAt":"2026-08-15T14:26:24.325Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}