{"record":{"id":"53cf80c4e888da0d","repo":"fatedier/frp","slug":"router-config-conflict","errorCode":null,"errorMessage":"router config conflict","messagePattern":"router config conflict","errorType":"exception","errorClass":"ErrRouterConfigConflict","httpStatus":null,"severity":"error","filePath":"pkg/util/vhost/router.go","lineNumber":11,"sourceCode":"package vhost\n\nimport (\n\t\"cmp\"\n\t\"errors\"\n\t\"slices\"\n\t\"strings\"\n\t\"sync\"\n)\n\nvar ErrRouterConfigConflict = errors.New(\"router config conflict\")\n\ntype routerByHTTPUser map[string][]*Router\n\ntype Routers struct {\n\tindexByDomain map[string]routerByHTTPUser\n\n\tmutex sync.RWMutex\n}\n\ntype Router struct {\n\tdomain   string\n\tlocation string\n\thttpUser string\n\n\t// store any object here\n\tpayload any\n}\n","sourceCodeStart":1,"sourceCodeEnd":29,"githubUrl":"https://github.com/fatedier/frp/blob/6c8a8d0a97d03b44e9528d30b30c70cb9d61b405/pkg/util/vhost/router.go#L1-L29","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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"],"exampleFix":"# before — two clients both claim web.example.com\n[[proxies]]\nname = \"web\"\ntype = \"http\"\ncustomDomains = [\"web.example.com\"]\n\n# after — load-balance via group instead of duplicates\n[[proxies]]\nname = \"web-1\"\ntype = \"http\"\ngroup = \"web\"\ngroupKey = \"shared\"\ncustomDomains = [\"web.example.com\"]","handlingStrategy":"validation","validationCode":"// frps side, before adding a vhost route\nif err := vhostRouter.Add(domain, location, httpUser, payload); err != nil {\n    if errors.Is(err, vhost.ErrRouterConfigConflict) {\n        return fmt.Errorf(\"route %s%s (user %q) already registered by another proxy\", domain, location, httpUser)\n    }\n}","typeGuard":"func isRouterConflict(err error) bool {\n    return errors.Is(err, vhost.ErrRouterConfigConflict)\n}","tryCatchPattern":"if err := router.Add(dom, loc, user, payload); errors.Is(err, vhost.ErrRouterConfigConflict) {\n    // reject the duplicate proxy registration with a clear message to the client\n}","preventionTips":["Give each HTTP proxy unique customDomains/subdomain + location combos; use groups for load balancing","Never clone an frpc instance without changing its domains"],"tags":["frp","go","vhost","routing","conflict","server"],"backgroundTag":null,"analyzedSha":"6c8a8d0a97d03b44e9528d30b30c70cb9d61b405","analyzedAt":"2026-08-15T06:53:27.215Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}