{"record":{"id":"e1807ae23c35948e","repo":"fatedier/frp","slug":"no-route-found-for-destination-s","errorCode":null,"errorMessage":"no route found for destination %s","messagePattern":"no route found for destination (.+?)","errorType":"console","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/vnet/controller.go","lineNumber":304,"sourceCode":"\tr.mu.Lock()\n\tdefer r.mu.Unlock()\n\tr.routes[name] = &routeElement{\n\t\troutes: routes,\n\t\tconn:   conn,\n\t}\n}\n\nfunc (r *clientRouter) findConn(dst net.IP) (io.Writer, error) {\n\tr.mu.RLock()\n\tdefer r.mu.RUnlock()\n\tfor _, re := range r.routes {\n\t\tfor _, route := range re.routes {\n\t\t\tif route.Contains(dst) {\n\t\t\t\treturn re.conn, nil\n\t\t\t}\n\t\t}\n\t}\n\treturn nil, fmt.Errorf(\"no route found for destination %s\", dst)\n}\n\nfunc (r *clientRouter) delRoute(name string) {\n\tr.mu.Lock()\n\tdefer r.mu.Unlock()\n\tdelete(r.routes, name)\n}\n\nfunc (r *clientRouter) removeConnRoute(conn io.Writer) {\n\tr.mu.Lock()\n\tdefer r.mu.Unlock()\n\tfor name, re := range r.routes {\n\t\tif re.conn == conn {\n\t\t\tdelete(r.routes, name)\n\t\t\treturn\n\t\t}\n\t}\n}","sourceCodeStart":286,"sourceCodeEnd":322,"githubUrl":"https://github.com/fatedier/frp/blob/6c8a8d0a97d03b44e9528d30b30c70cb9d61b405/pkg/vnet/controller.go#L286-L322","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["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\"]","Make sure routes are configured consistently on both frpc and frps vnet sections so registration completes","Add more-specific OS routes (or adjust routes) so non-tunnel traffic (internet) is not captured by the TUN device","Check the destination IP in the message against your route table with `ip route get <dst>`"],"exampleFix":"# before\n[vnet]\nroutes = [\"10.0.0.0/24\"]\n# app calls 192.168.5.20 -> no route found for destination 192.168.5.20\n\n# after\n[vnet]\nroutes = [\"10.0.0.0/24\", \"192.168.5.0/24\"]","handlingStrategy":"validation","validationCode":"// before sending, confirm dst is inside a configured vnet route\nfunc covered(dst net.IP, routes []*net.IPNet) bool {\n    for _, r := range routes { if r.Contains(dst) { return true } }\n    return false\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Enumerate every subnet your apps will reach and mirror it in vnet routes on both ends","After changing routes, restart frpc so registration messages refresh","Check `ip route get <dst>` on the client to see whether traffic enters utun as intended"],"tags":["vnet","network","routing","config"],"backgroundTag":null,"analyzedSha":"6c8a8d0a97d03b44e9528d30b30c70cb9d61b405","analyzedAt":"2026-08-15T06:53:27.215Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}