XTLS/Xray-core · error

unknown domain type:

Error message

unknown domain type: 

What it means

Returned by parseDomain when a protobuf Domain message has a Type outside the known enum values (Substr, Regex, Domain, Full). Since the switch has no matching case, the integer enum value (printed via the variadic errors.New — hence the empty-looking trailing placeholder in static analysis) is rejected. This indicates data written by a newer/unknown schema or corrupted geodata, not a user typo.

Source

Thrown at common/geodata/domain_matcher.go:227

	}
	return false
}

func parseDomain(d *Domain) (strmatcher.Matcher, error) {
	if d == nil {
		return nil, errors.New("domain must not be nil")
	}
	switch d.Type {
	case Domain_Substr:
		return strmatcher.Substr.New(strings.ToLower(d.Value))
	case Domain_Regex:
		return strmatcher.Regex.New(d.Value)
	case Domain_Domain:
		return strmatcher.Domain.New(strings.ToLower(d.Value))
	case Domain_Full:
		return strmatcher.Full.New(strings.ToLower(d.Value))
	default:
		return nil, errors.New("unknown domain type: ", d.Type)
	}
}

func newDomainMatcherFactory() DomainMatcherFactory {
	switch runtime.GOOS {
	case "ios", "android":
		return &CompactDomainMatcherFactory{shared: utils.NewWeakCacheMap[string, strmatcher.LinearAnyMatcher]()}
	default:
		return &MphDomainMatcherFactory{shared: utils.NewWeakCacheMap[string, strmatcher.MphValueMatcher]()}
	}
}

View on GitHub (pinned to 7d214f8b09)

Solutions

  1. Update xray-core to a version that understands the enum value in the error message (the type integer is appended at runtime).
  2. Re-download/regenerate the geosite.dat from the official source and verify its checksum.
  3. If producing Domain messages programmatically, only use Domain_Full/Domain_Domain/Domain_Substr/Domain_Regex constants.

Example fix

// before
d := &geodata.Domain{Type: geodata.Domain_Type(7), Value: "example.com"}

// after
d := &geodata.Domain{Type: geodata.Domain_Full, Value: "example.com"}
Defensive patterns

Strategy: type-guard

Validate before calling

switch d.Type {
case geodata.Domain_Full, geodata.Domain_Domain, geodata.Domain_Substr, geodata.Domain_Regex:
default:
    // reject before building matchers
}

Type guard

func isValidDomainType(t geodata.Domain_Type) bool {
    switch t {
    case geodata.Domain_Full, geodata.Domain_Domain, geodata.Domain_Substr, geodata.Domain_Regex:
        return true
    }
    return false
}

Prevention

When it happens

Trigger: Feeding BuildMatcher/CompactDomainMatcher rules whose DomainRule values carry Domain.Type = 4+ — e.g. a geosite.dat produced by a fork that extended the enum, or a hand-crafted protobuf with an unset/garbage type field (type defaults to 0=Full only when valid).

Common situations: Mixing dat files from incompatible Xray forks or newer proto schemas with an older binary; corrupted downloads flipping bytes inside the type field; tooling that constructs Domain messages with raw numeric types.

Related errors


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