fatedier/frp · error · ErrNoRouteFound
no route found
Error message
no route found
What it means
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.
Source
Thrown at pkg/util/vhost/http.go:36
"context"
"encoding/base64"
"errors"
"fmt"
stdlog "log"
"net"
"net/http"
"net/http/httputil"
"net/url"
"time"
libio "github.com/fatedier/golib/io"
"github.com/fatedier/golib/pool"
httppkg "github.com/fatedier/frp/pkg/util/http"
"github.com/fatedier/frp/pkg/util/log"
)
var ErrNoRouteFound = errors.New("no route found")
type HTTPReverseProxyOptions struct {
ResponseHeaderTimeoutS int64
}
type HTTPReverseProxy struct {
proxy http.Handler
vhostRouter *Routers
responseHeaderTimeout time.Duration
}
func NewHTTPReverseProxy(option HTTPReverseProxyOptions, vhostRouter *Routers) *HTTPReverseProxy {
if option.ResponseHeaderTimeoutS <= 0 {
option.ResponseHeaderTimeoutS = 60
}
rp := &HTTPReverseProxy{
responseHeaderTimeout: time.Duration(option.ResponseHeaderTimeoutS) * time.Second,View on GitHub (pinned to 6c8a8d0a97)
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)
Example fix
# before (frpc.toml) — domain typo'd [[proxies]] name = "web" type = "http" remotePort = 80 customDomains = ["exmaple.com"] # after customDomains = ["example.com"]
Defensive patterns
Strategy: validation
Validate before calling
// Before sending traffic, confirm a route exists (frps side)
if _, err := vhostRouter.Get(host, routePath, httpUser); errors.Is(err, vhost.ErrNoRouteFound) {
// no proxy registered for this host/path/user yet — register or fix the Host header
} Type guard
func isNoRouteFound(err error) bool {
return errors.Is(err, vhost.ErrNoRouteFound)
} Try / catch
if err := proxy.ServeHTTP(w, r); err != nil {
if errors.Is(err, vhost.ErrNoRouteFound) {
http.Error(w, "unknown vhost route — check proxy domain/location", http.StatusNotFound)
return
}
http.Error(w, err.Error(), http.StatusBadGateway)
} Prevention
- 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
When it happens
Trigger: 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.
Common situations: 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.
Related errors
- router config conflict
- send ${op} request to plugin error
- group auth failed
- group params invalid
- group should have same remote port
AI-assisted analysis of fatedier/frp@6c8a8d0a97 (2026-08-15).
Data as JSON: /api/errors/b41140fd8bcf1844.
Report an issue: GitHub.