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

  1. Replace the dat file from the official source and verify its checksum.
  2. Never overwrite dat files in place — write to a temp file and rename so readers see either old or new file.
  3. 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

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


AI-assisted analysis of XTLS/Xray-core@7d214f8b09 (2026-08-15). Data as JSON: /api/errors/c24fb5d844e23f56. Report an issue: GitHub.