{"record":{"id":"55e1acc9e5a6ff77","repo":"fatedier/frp","slug":"proxy-name-s-is-duplicated","errorCode":null,"errorMessage":"proxy name [%s] is duplicated","messagePattern":"proxy name \\[(.+?)\\] is duplicated","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/config/load.go","lineNumber":432,"sourceCode":"\n\tproxyCfgs := result.Proxies\n\tvisitorCfgs := result.Visitors\n\n\tproxyCfgs, visitorCfgs = FilterClientConfigurers(result.Common, proxyCfgs, visitorCfgs)\n\tproxyCfgs = CompleteProxyConfigurers(proxyCfgs)\n\tvisitorCfgs = CompleteVisitorConfigurers(visitorCfgs)\n\treturn result.Common, proxyCfgs, visitorCfgs, result.IsLegacyFormat, nil\n}\n\n// validateNoDuplicateNames rejects proxies or visitors that share a name. They are\n// keyed by name in the config sources, so a duplicate would otherwise be silently\n// overwritten and never started, with no error or log.\nfunc validateNoDuplicateNames(proxies []v1.ProxyConfigurer, visitors []v1.VisitorConfigurer) error {\n\tproxyNames := make(map[string]struct{}, len(proxies))\n\tfor _, p := range proxies {\n\t\tname := p.GetBaseConfig().Name\n\t\tif _, ok := proxyNames[name]; ok {\n\t\t\treturn fmt.Errorf(\"proxy name [%s] is duplicated\", name)\n\t\t}\n\t\tproxyNames[name] = struct{}{}\n\t}\n\n\tvisitorNames := make(map[string]struct{}, len(visitors))\n\tfor _, v := range visitors {\n\t\tname := v.GetBaseConfig().Name\n\t\tif _, ok := visitorNames[name]; ok {\n\t\t\treturn fmt.Errorf(\"visitor name [%s] is duplicated\", name)\n\t\t}\n\t\tvisitorNames[name] = struct{}{}\n\t}\n\n\treturn nil\n}\n\nfunc CompleteProxyConfigurers(proxies []v1.ProxyConfigurer) []v1.ProxyConfigurer {\n\tproxyCfgs := proxies","sourceCodeStart":414,"sourceCodeEnd":450,"githubUrl":"https://github.com/fatedier/frp/blob/6c8a8d0a97d03b44e9528d30b30c70cb9d61b405/pkg/config/load.go#L414-L450","documentation":"validateNoDuplicateNames runs after loading all proxy/visitor configurers in the new (TOML/YAML/JSON) format. Because proxies and visitors are keyed by name in maps, duplicates would silently overwrite each other; this check rejects a duplicated proxy name with 'proxy name [<name>] is duplicated' so nothing is silently dropped.","triggerScenarios":"Two [[proxies]] entries in frpc.toml with the same name; the same proxy defined both in the main file and again in an included file (includes are merged before this check); names differing only by whitespace that normalize to equality.","commonSituations":"Copying a [[proxies]] block and forgetting to change name; per-host include files that re-declare a shared base proxy; merging configs from multiple teams.","solutions":["Find the duplicate name (the message includes it) and rename one of the entries","If the duplicate comes from an include file, remove the copy from either the main file or the include","grep the main file plus all includes for 'name = \"<dup>\"' to catch cross-file collisions"],"exampleFix":"# before\n[[proxies]]\nname = \"web\"\n[[proxies]]\nname = \"web\"\n\n# after\n[[proxies]]\nname = \"web-a\"\n[[proxies]]\nname = \"web-b\"","handlingStrategy":"validation","validationCode":"names := sets.New[string]()\nfor _, p := range allProxies { if names.Has(p.GetBaseConfig().Name) { return fmt.Errorf(\"duplicate proxy %s\", p.GetBaseConfig().Name) }; names.Insert(p.GetBaseConfig().Name) }","typeGuard":null,"tryCatchPattern":"if err := config.LoadClientConfig(path, strict); err != nil { if strings.Contains(err.Error(), \"is duplicated\") { /* extract name, dedupe sources, reload */ } }","preventionTips":["Generate unique names with a host/service prefix","Deduplicate across main file and includes in CI","grep for name collisions before merge"],"tags":["config","proxy","duplicate","validation","includes"],"backgroundTag":null,"analyzedSha":"6c8a8d0a97d03b44e9528d30b30c70cb9d61b405","analyzedAt":"2026-08-15T06:53:27.215Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}