XTLS/Xray-core · error

invalid system route {cidr}

Error message

invalid system route {cidr}

What it means

For each entry of the tun inbound's "autoSystemRoutingTable" (a.k.a. included routes), Xray parses the string with netip.ParsePrefix and rejects non-CIDR values. Unlike gateway addresses, these entries MUST include an explicit prefix length (e.g. "0.0.0.0/0"), because a bare IP does not describe a route.

Source

Thrown at proxy/tun/tun_linux.go:274

	for i := len(t.interfaceAddresses) - 1; i >= 0; i-- {
		address := t.interfaceAddresses[i]
		if err := netlink.AddrDel(t.tunLink, &address); err != nil {
			errs = append(errs, errors.New("failed to delete interface address ", address.String()).Base(err))
		}
	}
	t.interfaceAddresses = nil
	return errors.Combine(errs...)
}

func (t *LinuxTun) setSystemRoutes() error {
	if len(t.options.AutoSystemRoutingTable) == 0 {
		return nil
	}
	tunIndex := t.tunLink.Attrs().Index
	for _, cidr := range t.options.AutoSystemRoutingTable {
		prefix, err := netip.ParsePrefix(cidr)
		if err != nil {
			return errors.New("invalid system route ", cidr).Base(err)
		}
		prefix = prefix.Masked()
		_, ipNet, _ := net.ParseCIDR(prefix.String())
		route := netlink.Route{
			LinkIndex: tunIndex,
			Dst:       ipNet,
			Priority:  1,
		}
		if err := netlink.RouteAdd(&route); err != nil {
			_ = t.unsetSystemRoutes()
			return errors.New("failed to add system route ", cidr).Base(err)
		}
		t.systemRoutes = append(t.systemRoutes, route)
	}
	return nil
}

func (t *LinuxTun) unsetSystemRoutes() error {

View on GitHub (pinned to 7d214f8b09)

Solutions

  1. Write every route as an explicit CIDR: "192.168.0.0/24", "0.0.0.0/1", host routes as "1.1.1.1/32"
  2. Remove empty or placeholder entries from the list
  3. Validate the whole list with netip.ParsePrefix before launching Xray

Example fix

// before
"autoSystemRoutingTable": ["192.168.0.0"]

// after
"autoSystemRoutingTable": ["192.168.0.0/24"]
Defensive patterns

Strategy: validation

Validate before calling

for _, cidr := range cfg.AutoSystemRoutingTable {
	if _, err := netip.ParsePrefix(cidr); err != nil {
		log.Fatalf("bad route %q: must be CIDR like 10.0.0.0/8", cidr)
	}
}

Prevention

When it happens

Trigger: An entry like "192.168.0.0" without "/24", "1.1.1.1/99" (bad prefix), "::/0" mixed with malformed strings, or stray quotes/whitespace in the JSON/YAML list.

Common situations: Users writing bare IPs expecting a /32 host route; converting configs from other VPN tools that accept masks; JSON edits introducing empty strings.

Related errors


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