XTLS/Xray-core · error
varint overflow
Error message
varint overflow
What it means
Returned by decodeVarint while scanning the dat file's entry framing: a varint field continued past 64 bits (10+ bytes with the high bit set). Well-formed geodata never has such varints, so this unambiguously signals byte-stream corruption — the scanner has lost alignment or the file is damaged. It surfaces wrapped through the load/check paths.
Source
Thrown at common/geodata/geodat_loader.go:81
return nil, errors.New("error unmarshal Site in ", file, ":", code).Base(err)
}
return geosite.Domain, nil
}
func decodeVarint(br *bufio.Reader) (uint64, error) {
var x uint64
for shift := uint(0); shift < 64; shift += 7 {
b, err := br.ReadByte()
if err != nil {
return 0, err
}
x |= (uint64(b) & 0x7F) << shift
if (b & 0x80) == 0 {
return x, nil
}
}
// The number is too large to represent in a 64-bit value.
return 0, errors.New("varint overflow")
}
func find(r io.Reader, code []byte, readBody bool) ([]byte, error) {
codeL := len(code)
if codeL == 0 {
return nil, errors.New("empty code")
}
br := bufio.NewReaderSize(r, 64*1024)
need := 2 + codeL // TODO: if code too long
prefixBuf := make([]byte, need)
for {
if _, err := br.ReadByte(); err != nil {
return nil, err
}
x, err := decodeVarint(br)View on GitHub (pinned to 7d214f8b09)
Solutions
- Replace the dat file from the official source and verify its checksum.
- Never overwrite dat files in place — write to a temp file and rename so readers see either old or new file.
- Ensure the file passed as geodata really is a protobuf dat file, not an error page or archive.
Example fix
# before $ cp new_geoip.dat /etc/xray/geoip.dat # in-place overwrite while xray reads # after $ cp new_geoip.dat /etc/xray/geoip.dat.tmp && mv /etc/xray/geoip.dat.tmp /etc/xray/geoip.dat
Defensive patterns
Strategy: retry
Validate before calling
// Detect non-protobuf files early: a dat file starting with '<' (HTML) or of tiny size is not geodata
if b, _ := os.ReadFile(p); len(b) > 0 && b[0] == '<' { /* re-provision */ } Try / catch
// After any find()/load error chain containing "varint overflow", re-download the dat atomically and retry once
Prevention
- Atomic-replace dat files; never write in place
- Keep mirrors out of the dat supply chain
When it happens
Trigger: find() walking a dat file whose bytes are shifted/corrupted (bad download, in-place overwrite during read, wrong file type passed as geodata) so a length field decodes to a >64-bit varint.
Common situations: Dat files replaced non-atomically while xray reads them; HTML/text files renamed to .dat; bit rot or truncated-then-appended files.
Related errors
- invalid body length:
- failed to load code
- error unmarshal IP in
- error unmarshal Site in
- illegal ip rule:
AI-assisted analysis of XTLS/Xray-core@7d214f8b09 (2026-08-15).
Data as JSON: /api/errors/c24fb5d844e23f56.
Report an issue: GitHub.