{"record":{"id":"b41140fd8bcf1844","repo":"fatedier/frp","slug":"no-route-found","errorCode":null,"errorMessage":"no route found","messagePattern":"no route found","errorType":"http","errorClass":"ErrNoRouteFound","httpStatus":404,"severity":"error","filePath":"pkg/util/vhost/http.go","lineNumber":36,"sourceCode":"\t\"context\"\n\t\"encoding/base64\"\n\t\"errors\"\n\t\"fmt\"\n\tstdlog \"log\"\n\t\"net\"\n\t\"net/http\"\n\t\"net/http/httputil\"\n\t\"net/url\"\n\t\"time\"\n\n\tlibio \"github.com/fatedier/golib/io\"\n\t\"github.com/fatedier/golib/pool\"\n\n\thttppkg \"github.com/fatedier/frp/pkg/util/http\"\n\t\"github.com/fatedier/frp/pkg/util/log\"\n)\n\nvar ErrNoRouteFound = errors.New(\"no route found\")\n\ntype HTTPReverseProxyOptions struct {\n\tResponseHeaderTimeoutS int64\n}\n\ntype HTTPReverseProxy struct {\n\tproxy       http.Handler\n\tvhostRouter *Routers\n\n\tresponseHeaderTimeout time.Duration\n}\n\nfunc NewHTTPReverseProxy(option HTTPReverseProxyOptions, vhostRouter *Routers) *HTTPReverseProxy {\n\tif option.ResponseHeaderTimeoutS <= 0 {\n\t\toption.ResponseHeaderTimeoutS = 60\n\t}\n\trp := &HTTPReverseProxy{\n\t\tresponseHeaderTimeout: time.Duration(option.ResponseHeaderTimeoutS) * time.Second,","sourceCodeStart":18,"sourceCodeEnd":54,"githubUrl":"https://github.com/fatedier/frp/blob/6c8a8d0a97d03b44e9528d30b30c70cb9d61b405/pkg/util/vhost/http.go#L18-L54","documentation":"ErrNoRouteFound is the sentinel for the vhost HTTP router: the reverse proxy in pkg/util/vhost/http.go found no registered route matching the request. At the return site it is wrapped with host, URL and HTTP user ('no route found: host url user') so you can see exactly which dimensions failed to match. Routes are added by frps when HTTP/HTTPS-type proxies register their domain/location.","triggerScenarios":"Browsing to a host:port served by frps vhostHTTPPort before any matching proxy is registered; wrong Host header (domain not configured in any proxy's customDomains/subdomain); location path not matching any proxy's locations; vhostHTTPPassword/HTTPUser mismatch when basic-auth vhost is enabled.","commonSituations":"DNS points to the frps server but the frpc proxy with that customDomain is offline; subdomain configured but subdomainHost not set on frps (so the full host never matches); typo in domain; requests arriving with a port appended to Host (host:8080) not matching; proxy registered under a different httpUser.","solutions":["Match the request Host header exactly to a proxy's customDomains or group.subdomain + frps subdomainHost","Confirm the frpc owning the HTTP proxy is connected and the proxy reached Running state","If using subdomains, set subdomainHost on frps and use subdomain = \"x\" so x.subdomainHost resolves","For multi-location proxies, check the request path matches one of the configured locations (prefix match)"],"exampleFix":"# before (frpc.toml) — domain typo'd\n[[proxies]]\nname = \"web\"\ntype = \"http\"\nremotePort = 80\ncustomDomains = [\"exmaple.com\"]\n\n# after\ncustomDomains = [\"example.com\"]","handlingStrategy":"validation","validationCode":"// Before sending traffic, confirm a route exists (frps side)\nif _, err := vhostRouter.Get(host, routePath, httpUser); errors.Is(err, vhost.ErrNoRouteFound) {\n    // no proxy registered for this host/path/user yet — register or fix the Host header\n}","typeGuard":"func isNoRouteFound(err error) bool {\n    return errors.Is(err, vhost.ErrNoRouteFound)\n}","tryCatchPattern":"if err := proxy.ServeHTTP(w, r); err != nil {\n    if errors.Is(err, vhost.ErrNoRouteFound) {\n        http.Error(w, \"unknown vhost route — check proxy domain/location\", http.StatusNotFound)\n        return\n    }\n    http.Error(w, err.Error(), http.StatusBadGateway)\n}","preventionTips":["Point DNS at frps only after the HTTP proxy with that customDomain is Running","Set subdomainHost on frps and use subdomain (not full domain) consistently; avoid port suffixes in the Host header"],"tags":["frp","go","vhost","http","routing","server"],"backgroundTag":null,"analyzedSha":"6c8a8d0a97d03b44e9528d30b30c70cb9d61b405","analyzedAt":"2026-08-15T06:53:27.215Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}