fatedier/frp · error

visitor name [%s] is duplicated

Error message

visitor name [%s] is duplicated

What it means

The visitor counterpart of the duplicate-name check: after aggregation, two visitors sharing one name make 'visitor name [<name>] is duplicated' fail the load, preventing the map-keyed silent overwrite that would otherwise drop one visitor.

Source

Thrown at pkg/config/load.go:441

// validateNoDuplicateNames rejects proxies or visitors that share a name. They are
// keyed by name in the config sources, so a duplicate would otherwise be silently
// overwritten and never started, with no error or log.
func validateNoDuplicateNames(proxies []v1.ProxyConfigurer, visitors []v1.VisitorConfigurer) error {
	proxyNames := make(map[string]struct{}, len(proxies))
	for _, p := range proxies {
		name := p.GetBaseConfig().Name
		if _, ok := proxyNames[name]; ok {
			return fmt.Errorf("proxy name [%s] is duplicated", name)
		}
		proxyNames[name] = struct{}{}
	}

	visitorNames := make(map[string]struct{}, len(visitors))
	for _, v := range visitors {
		name := v.GetBaseConfig().Name
		if _, ok := visitorNames[name]; ok {
			return fmt.Errorf("visitor name [%s] is duplicated", name)
		}
		visitorNames[name] = struct{}{}
	}

	return nil
}

func CompleteProxyConfigurers(proxies []v1.ProxyConfigurer) []v1.ProxyConfigurer {
	proxyCfgs := proxies
	for _, c := range proxyCfgs {
		c.Complete()
	}
	return proxyCfgs
}

func CompleteVisitorConfigurers(visitors []v1.VisitorConfigurer) []v1.VisitorConfigurer {
	visitorCfgs := visitors
	for _, c := range visitorCfgs {

View on GitHub (pinned to 6c8a8d0a97)

Solutions

  1. Rename one of the visitor entries sharing the name
  2. Search main config and all includes for the duplicated visitor name and keep a single definition
  3. Use a naming convention (host-service-visitor) to avoid collisions across include files

Example fix

# before
[[visitors]]
name = "stcp-visitor"
[[visitors]]
name = "stcp-visitor"

# after
[[visitors]]
name = "stcp-visitor-a"
[[visitors]]
name = "stcp-visitor-b"
Defensive patterns

Strategy: validation

Validate before calling

names := sets.New[string]()
for _, v := range allVisitors { if names.Has(v.GetBaseConfig().Name) { return fmt.Errorf("duplicate visitor %s", v.GetBaseConfig().Name) }; names.Insert(v.GetBaseConfig().Name) }

Try / catch

if err := config.LoadClientConfig(path, strict); err != nil { if strings.Contains(err.Error(), "visitor name") && strings.Contains(err.Error(), "duplicated") { /* rename and reload */ } }

Prevention

When it happens

Trigger: Two [[visitors]] entries in frpc.toml sharing one name, or the same visitor defined in the main file and again in an included file — includes are merged into one list before this check runs.

Common situations: Copy-pasted [[visitors]] blocks without renaming; visitors for the same serverName defined in both the main config and an include file; multiple operators adding visitors for the same secret service.

Related errors


AI-assisted analysis of fatedier/frp@6c8a8d0a97 (2026-08-15). Data as JSON: /api/errors/2df393edce8762c6. Report an issue: GitHub.