fatedier/frp · error

no route found for destination %s

Error message

no route found for destination %s

What it means

vnet client-side routing error: the router (clientRouter.findConn) has no registered route whose CIDR contains the destination IP of the packet being tunneled. The vnet TUN device captured a packet whose destination lies outside every route configured/registered on this side; the message names the unmatched destination IP.

Source

Thrown at pkg/vnet/controller.go:304

	r.mu.Lock()
	defer r.mu.Unlock()
	r.routes[name] = &routeElement{
		routes: routes,
		conn:   conn,
	}
}

func (r *clientRouter) findConn(dst net.IP) (io.Writer, error) {
	r.mu.RLock()
	defer r.mu.RUnlock()
	for _, re := range r.routes {
		for _, route := range re.routes {
			if route.Contains(dst) {
				return re.conn, nil
			}
		}
	}
	return nil, fmt.Errorf("no route found for destination %s", dst)
}

func (r *clientRouter) delRoute(name string) {
	r.mu.Lock()
	defer r.mu.Unlock()
	delete(r.routes, name)
}

func (r *clientRouter) removeConnRoute(conn io.Writer) {
	r.mu.Lock()
	defer r.mu.Unlock()
	for name, re := range r.routes {
		if re.conn == conn {
			delete(r.routes, name)
			return
		}
	}
}

View on GitHub (pinned to 6c8a8d0a97)

Solutions

  1. Add a CIDR covering the destination to the routes of the side that originates the traffic: routes = ["10.0.0.0/24", "192.168.5.0/24"]
  2. Make sure routes are configured consistently on both frpc and frps vnet sections so registration completes
  3. Add more-specific OS routes (or adjust routes) so non-tunnel traffic (internet) is not captured by the TUN device
  4. Check the destination IP in the message against your route table with `ip route get <dst>`

Example fix

# before
[vnet]
routes = ["10.0.0.0/24"]
# app calls 192.168.5.20 -> no route found for destination 192.168.5.20

# after
[vnet]
routes = ["10.0.0.0/24", "192.168.5.0/24"]
Defensive patterns

Strategy: validation

Validate before calling

// before sending, confirm dst is inside a configured vnet route
func covered(dst net.IP, routes []*net.IPNet) bool {
    for _, r := range routes { if r.Contains(dst) { return true } }
    return false
}

Prevention

When it happens

Trigger: frpc with vnet enabled: an application sends traffic to an IP that is not inside any CIDR listed in the vnet routes (or the peer has not registered routes yet). Also a timing window right after startup before route registration messages arrive from the other side.

Common situations: routes on frpc cover 10.0.0.0/24 but the app targets 192.168.x.x;忘记 to mirror routes on both ends; accessing the TUN interface IP itself; sending to a public IP that should stay outside the tunnel but the OS routed it into utun.

Related errors


AI-assisted analysis of fatedier/frp@6c8a8d0a97 (2026-08-15). Data as JSON: /api/errors/e1807ae23c35948e. Report an issue: GitHub.