XTLS/Xray-core · error
failed to add system route {cidr}
Error message
failed to add system route {cidr} What it means
After parsing a CIDR, Xray installs a netlink route (LinkIndex = TUN, Priority 1) via netlink.RouteAdd. Failure rolls back previously added routes and returns this wrapped error. Common base causes: EEXIST (route already present with same metric), EPERM (no CAP_NET_ADMIN), ENETUNREACH (prefix not maskable/routable), or link index invalid.
Source
Thrown at proxy/tun/tun_linux.go:285
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 {
var errs []error
for i := len(t.systemRoutes) - 1; i >= 0; i-- {
route := t.systemRoutes[i]
if err := netlink.RouteDel(&route); err != nil {
errs = append(errs, errors.New("failed to delete system route").Base(err))
}
}
t.systemRoutes = nil
return errors.Combine(errs...)
}
View on GitHub (pinned to 7d214f8b09)
Solutions
- Run with root/CAP_NET_ADMIN privileges
- Remove stale routes before start: `ip route del <cidr> dev <tun>` or flush the table
- Deduplicate overlapping CIDRs in autoSystemRoutingTable
Example fix
# before: stale route ip route # 0.0.0.0/1 dev tun0 metric 1 still present # after ip route del 0.0.0.0/1 dev tun0 2>/dev/null || true # then start xray
Defensive patterns
Strategy: fallback
Validate before calling
// pre-flight: drop stale routes that xray will install
for _, cidr := range cfg.AutoSystemRoutingTable {
_ = exec.Command("ip", "route", "del", cidr, "dev", tunName).Run()
} Try / catch
if err := tun.Start(); err != nil {
if strings.Contains(err.Error(), "failed to add system route") {
// clean routes, then fall back to a single retry
}
} Prevention
- Ensure CAP_NET_ADMIN before starting tun mode
- Clear leftover routes from crashed runs before start
- Avoid running two VPN stacks managing the same prefixes
When it happens
Trigger: Routing table already contains the same prefix pointing at the TUN (leftover from a crashed run); running unprivileged; overlapping more-specific route that kernel merges differently; duplicates inside autoSystemRoutingTable.
Common situations: Restart after an unclean shutdown that left routes behind; concurrent VPN clients fighting over default routes; containers missing NET_ADMIN; duplicating 0.0.0.0/0 twice.
Related errors
- failed to add interface address {address}
- failed to delete system route
- invalid interface address {address}
- failed to delete interface address {address}
- invalid system route {cidr}
AI-assisted analysis of XTLS/Xray-core@7d214f8b09 (2026-08-15).
Data as JSON: /api/errors/7c77bfc5408eb556.
Report an issue: GitHub.