slackhq/nebula · error
entry %v.route in tun.routes is not contained within the con
Error message
entry %v.route in tun.routes is not contained within the configured vpn networks; route: %v, networks: %v
What it means
The parsed route CIDR is valid but not contained within any of the configured VPN networks for this host. parseRoutes checks each route against the host's allowed networks (network.Contains(cidr.Addr()) && cidr.Bits() >= network.Bits()) and rejects routes that would reach outside the VPN's address space, listing the route and the allowed networks.
Source
Thrown at overlay/route.go:135
Install: true,
MTU: mtu,
}
r.Cidr, err = netip.ParsePrefix(fmt.Sprintf("%v", rRoute))
if err != nil {
return nil, fmt.Errorf("entry %v.route in tun.routes failed to parse: %v", i+1, err)
}
found := false
for _, network := range networks {
if network.Contains(r.Cidr.Addr()) && r.Cidr.Bits() >= network.Bits() {
found = true
break
}
}
if !found {
return nil, fmt.Errorf(
"entry %v.route in tun.routes is not contained within the configured vpn networks; route: %v, networks: %v",
i+1,
r.Cidr.String(),
networks,
)
}
routes[i] = r
}
return routes, nil
}
func parseUnsafeRoutes(c *config.C, networks []netip.Prefix) ([]Route, error) {
var err error
r := c.Get("tun.unsafe_routes")
if r == nil {View on GitHub (pinned to dd8f660c0a)
Solutions
- Add the desired network to the host's configured vpn networks (its allowed networks in the CA/certificate or networks list) so the route is contained
- Narrow the route to fit within an already-configured network (e.g. 10.0.1.0/24 instead of 10.0.0.0/8)
- Compare the printed route against the printed networks list to see the containment mismatch
- If routing beyond the VPN is genuinely needed, update the certificate/host network configuration first — never try to bypass this check
Example fix
// before: host networks = 10.0.0.0/24, route outside it
routes:
- mtu: 1300
route: 192.168.1.0/24
// after: either change route to fit, or extend host networks
tun:
routes:
- mtu: 1300
route: 10.0.0.0/24 Defensive patterns
Strategy: validation
Validate before calling
cidr := netip.MustParsePrefix(fmt.Sprintf("%v", m["route"]))
contained := false
for _, n := range networks {
if n.Contains(cidr.Addr()) && cidr.Bits() >= n.Bits() {
contained = true
break
}
}
if !contained {
return fmt.Errorf("route %s not within configured vpn networks %v", cidr, networks)
} Prevention
- Before adding a route, confirm its CIDR is inside a configured vpn network for the host
- Route prefix must be equal to or longer (more specific) than the network prefix
- When adding new subnets, update host/certificate networks first
- Keep host network definitions and tun.routes in sync through review/CI checks
When it happens
Trigger: getAllRoutesFromConfig reads a tun.routes entry whose CIDR falls outside (or is broader than) the networks configured for the host/certificate, e.g. route 192.168.1.0/24 when the VPN only covers 10.0.0.0/24, or route 10.0.0.0/8 when the host network is 10.0.1.0/24 (route broader than the allowed network).
Common situations: Operator wants to route additional corporate subnets but forgot to add them to the host's allowed networks; copy-pasting routes from another nebula/overlay deployment; prefix-length mistakes making the route broader than the network; intentional route escalation that the config correctly rejects as a security guard.
Related errors
- Empty configuration
- group should contain a single value, an array with more than
- stats.host can not be empty
- stats.listen should not be empty
- stats.path should not be empty
AI-assisted analysis of slackhq/nebula@dd8f660c0a (2026-09-03).
Data as JSON: /api/errors/3ea5498f5f72884c.
Report an issue: GitHub.