XTLS/Xray-core · error

error unmarshal Site in

Error message

error unmarshal Site in 

What it means

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.

Source

Thrown at common/geodata/geodat_loader.go:63

		return nil, err
	}
	defer runtime.GC() // peak mem
	var geoip GeoIP
	if err := proto.Unmarshal(bs, &geoip); err != nil {
		return nil, errors.New("error unmarshal IP in ", file, ":", code).Base(err)
	}
	return geoip.Cidr, nil
}

func loadSite(file, code string) ([]*Domain, error) {
	bs, err := loadFile(file, code)
	if err != nil {
		return nil, err
	}
	defer runtime.GC() // peak mem
	var geosite GeoSite
	if err := proto.Unmarshal(bs, &geosite); err != nil {
		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")

View on GitHub (pinned to 7d214f8b09)

Solutions

  1. Re-download the official geosite.dat (dlc.dat) and verify integrity before restart.
  2. Stop writing dat files in-place while xray runs; write to a temp file and atomically rename.
  3. Update core if the dat producer targets a newer schema.

Example fix

# before (ops)
$ curl -s example-mirror/geosite.dat -o /etc/xray/geosite.dat # corrupt

# after
$ curl -sL https://github.com/v2fly/domain-list-community/releases/latest/download/dlc.dat -o /tmp/geosite.dat
$ mv /tmp/geosite.dat /etc/xray/geosite.dat # atomic replace, not in-place overwrite
Defensive patterns

Strategy: validation

Validate before calling

// Hash-verify geosite.dat (dlc.dat) against the published checksum before start

Try / catch

domains, err := loadSite(file, code)
if err != nil && strings.Contains(err.Error(), "error unmarshal Site") { /* replace dat file */ }

Prevention

When it happens

Trigger: 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.

Common situations: 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.

Related errors


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