{"record":{"id":"fd217fd549351857","repo":"fatedier/frp","slug":"no-route-found-for-source-s","errorCode":null,"errorMessage":"no route found for source %s","messagePattern":"no route found for source (.+?)","errorType":"console","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/vnet/controller.go","lineNumber":341,"sourceCode":"\n// Server router (based solely on source IP routing)\ntype serverRouter struct {\n\tsrcIPConns map[string]io.Writer // Source IP string to connection mapping\n\tmu         sync.RWMutex\n}\n\nfunc newServerRouter() *serverRouter {\n\treturn &serverRouter{\n\t\tsrcIPConns: make(map[string]io.Writer),\n\t}\n}\n\nfunc (r *serverRouter) findConnBySrc(src net.IP) (io.Writer, error) {\n\tr.mu.RLock()\n\tdefer r.mu.RUnlock()\n\tconn, exists := r.srcIPConns[src.String()]\n\tif !exists {\n\t\treturn nil, fmt.Errorf(\"no route found for source %s\", src)\n\t}\n\treturn conn, nil\n}\n\nfunc (r *serverRouter) registerSrcIP(src net.IP, conn io.Writer) {\n\tkey := src.String()\n\n\tr.mu.RLock()\n\texistingConn, ok := r.srcIPConns[key]\n\tr.mu.RUnlock()\n\n\t// If the entry exists and the connection is the same, no need to do anything.\n\tif ok && existingConn == conn {\n\t\treturn\n\t}\n\n\t// Acquire write lock to update the map.\n\tr.mu.Lock()","sourceCodeStart":323,"sourceCodeEnd":359,"githubUrl":"https://github.com/fatedier/frp/blob/6c8a8d0a97d03b44e9528d30b30c70cb9d61b405/pkg/vnet/controller.go#L323-L359","documentation":"vnet server-side routing error: serverRouter.findConnBySrc maps source IPs to the client connection that registered them; when a packet's source IP string is not present in srcIPConns, this error is returned. It means the server received tunneled traffic claiming a source address that no frpc connection has registered.","triggerScenarios":"frps vnet router forwarding a packet whose source IP was never registered via route-registration messages; a second frpc overwriting/deregistering routes while traffic is in flight; race at session teardown where routes are removed before queued packets are forwarded; source NAT changing IPs so they no longer equal the registered keys.","commonSituations":"Routes not configured on frpc so it never registers those source prefixes; multiple clients competing for the same vnet address ranges; stale sessions after a client reconnect — old routes removed, peer still sending from those IPs.","solutions":["Ensure frpc's vnet section lists the address ranges it will source traffic from so registration happens at connect","Avoid overlapping route/address ranges between multiple vnet clients connecting to the same frps","On client restart, give the vnet a moment for re-registration; reconnect the client if errors persist","Verify with the source IP in the message which client should own it and add that prefix to its routes"],"exampleFix":"# before (frpc has no routes; peer sends from 10.0.0.5)\n[vnet]\nenabled = true\n\n# after\n[vnet]\nenabled = true\naddress = [\"10.0.0.1/24\"]\nroutes = [\"10.0.0.0/24\"]","handlingStrategy":"fallback","validationCode":"// ensure the originating side registers its source prefixes\n// frpc.toml: vnet.routes must include the ranges traffic will come FROM","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Give each vnet client unique, non-overlapping address ranges","Expect transient no-source-route errors right after reconnects; alert only on persistence","Keep frpc and frps versions aligned so route registration semantics match"],"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"}