{"record":{"id":"07a04c88f6a36a5b","repo":"XTLS/Xray-core","slug":"error-unmarshal-site-in","errorCode":null,"errorMessage":"error unmarshal Site in ","messagePattern":"error unmarshal Site in ","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"common/geodata/geodat_loader.go","lineNumber":63,"sourceCode":"\t\treturn nil, err\n\t}\n\tdefer runtime.GC() // peak mem\n\tvar geoip GeoIP\n\tif err := proto.Unmarshal(bs, &geoip); err != nil {\n\t\treturn nil, errors.New(\"error unmarshal IP in \", file, \":\", code).Base(err)\n\t}\n\treturn geoip.Cidr, nil\n}\n\nfunc loadSite(file, code string) ([]*Domain, error) {\n\tbs, err := loadFile(file, code)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\tdefer runtime.GC() // peak mem\n\tvar geosite GeoSite\n\tif err := proto.Unmarshal(bs, &geosite); err != nil {\n\t\treturn nil, errors.New(\"error unmarshal Site in \", file, \":\", code).Base(err)\n\t}\n\treturn geosite.Domain, nil\n}\n\nfunc decodeVarint(br *bufio.Reader) (uint64, error) {\n\tvar x uint64\n\tfor shift := uint(0); shift < 64; shift += 7 {\n\t\tb, err := br.ReadByte()\n\t\tif err != nil {\n\t\t\treturn 0, err\n\t\t}\n\t\tx |= (uint64(b) & 0x7F) << shift\n\t\tif (b & 0x80) == 0 {\n\t\t\treturn x, nil\n\t\t}\n\t}\n\t// The number is too large to represent in a 64-bit value.\n\treturn 0, errors.New(\"varint overflow\")","sourceCodeStart":45,"sourceCodeEnd":81,"githubUrl":"https://github.com/XTLS/Xray-core/blob/7d214f8b094f75322fa3990f8aadad1c912f24f5/common/geodata/geodat_loader.go#L45-L81","documentation":"Wrapped error from loadSite: identical failure mode to the GeoIP case but for GeoSite entries — proto.Unmarshal of the located entry's bytes into a GeoSite message fails. The underlying protobuf error is chained via .Base; the message names the geosite file and code that could not be decoded.","triggerScenarios":"loadSite('geosite.dat', code) where the matched entry body is not valid GeoSite protobuf — truncated body (body length lied), fork-schema dat, or byte-level corruption from a bad mirror.","commonSituations":"Corrupted geosite.dat downloads; community 'merged/extended' dat files built with incompatible tools; partial writes when the dat file was replaced while xray was reading it.","solutions":["Re-download the official geosite.dat (dlc.dat) and verify integrity before restart.","Stop writing dat files in-place while xray runs; write to a temp file and atomically rename.","Update core if the dat producer targets a newer schema."],"exampleFix":"# before (ops)\n$ curl -s example-mirror/geosite.dat -o /etc/xray/geosite.dat # corrupt\n\n# after\n$ curl -sL https://github.com/v2fly/domain-list-community/releases/latest/download/dlc.dat -o /tmp/geosite.dat\n$ mv /tmp/geosite.dat /etc/xray/geosite.dat # atomic replace, not in-place overwrite","handlingStrategy":"validation","validationCode":"// Hash-verify geosite.dat (dlc.dat) against the published checksum before start","typeGuard":null,"tryCatchPattern":"domains, err := loadSite(file, code)\nif err != nil && strings.Contains(err.Error(), \"error unmarshal Site\") { /* replace dat file */ }","preventionTips":["Update dat files via temp-file + rename","Avoid third-party converters for geosite data"],"tags":["geodata","protobuf","corruption","geosite","xray"],"backgroundTag":null,"analyzedSha":"7d214f8b094f75322fa3990f8aadad1c912f24f5","analyzedAt":"2026-08-15T14:26:24.325Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}