fatedier/frp · error · ErrRouterConfigConflict
router config conflict
Error message
router config conflict
What it means
ErrRouterConfigConflict is returned by Routers.Add (pkg/util/vhost/router.go:43) when a route with the same (domain, location, httpUser) triple is already registered. frps calls this when an HTTP/HTTPS/TCPMux proxy tries to bind a vhost route; duplicate registration is rejected to keep routing unambiguous.
Source
Thrown at pkg/util/vhost/router.go:11
package vhost
import (
"cmp"
"errors"
"slices"
"strings"
"sync"
)
var ErrRouterConfigConflict = errors.New("router config conflict")
type routerByHTTPUser map[string][]*Router
type Routers struct {
indexByDomain map[string]routerByHTTPUser
mutex sync.RWMutex
}
type Router struct {
domain string
location string
httpUser string
// store any object here
payload any
}
View on GitHub (pinned to 6c8a8d0a97)
Solutions
- Give each proxy a unique domain/subdomain (or distinct locations) — only one proxy may own a given host+location+user triple
- If you cloned a client, stop the duplicate frpc instance or edit its config to use different domains
- If a stale route is suspected, wait for frps to reap the dead connection's proxies or restart frps
- For load balancing across clients, use the group feature with the same group name instead of duplicate routes
Example fix
# before — two clients both claim web.example.com [[proxies]] name = "web" type = "http" customDomains = ["web.example.com"] # after — load-balance via group instead of duplicates [[proxies]] name = "web-1" type = "http" group = "web" groupKey = "shared" customDomains = ["web.example.com"]
Defensive patterns
Strategy: validation
Validate before calling
// frps side, before adding a vhost route
if err := vhostRouter.Add(domain, location, httpUser, payload); err != nil {
if errors.Is(err, vhost.ErrRouterConfigConflict) {
return fmt.Errorf("route %s%s (user %q) already registered by another proxy", domain, location, httpUser)
}
} Type guard
func isRouterConflict(err error) bool {
return errors.Is(err, vhost.ErrRouterConfigConflict)
} Try / catch
if err := router.Add(dom, loc, user, payload); errors.Is(err, vhost.ErrRouterConfigConflict) {
// reject the duplicate proxy registration with a clear message to the client
} Prevention
- Give each HTTP proxy unique customDomains/subdomain + location combos; use groups for load balancing
- Never clone an frpc instance without changing its domains
When it happens
Trigger: Two frpc clients (or two proxies in one client) both claiming the same customDomain/subdomain with the same location and httpUser; a stale proxy not yet cleaned up when a new login re-registers the same route; tcpmux HTTPConnect with duplicate passthrough mapping.
Common situations: Running the same frpc config on two machines pointed at one frps (e.g. after cloning a VM); re-login after connection flapping where the old route has not been released; one proxy uses customDomains overlapping another's wildcard route with identical location.
Related errors
- no route found
- port already used
- send ${op} request to plugin error
- group auth failed
- group params invalid
AI-assisted analysis of fatedier/frp@6c8a8d0a97 (2026-08-15).
Data as JSON: /api/errors/53cf80c4e888da0d.
Report an issue: GitHub.