fatedier/frp · error
proxy %s role should be 'server' or 'visitor'
Error message
proxy %s role should be 'server' or 'visitor'
What it means
Legacy ini loader: each non-common, non-range section must declare role = server or role = visitor (defaulting to server when role is empty). Any other value — including typos — hits the default branch and abort config loading with this error.
Source
Thrown at pkg/config/legacy/client.go:283
if roleType == "" {
roleType = "server"
}
switch roleType {
case "server":
newConf, newErr := NewProxyConfFromIni(prefix, name, section)
if newErr != nil {
return nil, nil, fmt.Errorf("failed to parse proxy %s, err: %v", name, newErr)
}
proxyConfs[prefix+name] = newConf
case "visitor":
newConf, newErr := NewVisitorConfFromIni(prefix, name, section)
if newErr != nil {
return nil, nil, fmt.Errorf("failed to parse visitor %s, err: %v", name, newErr)
}
visitorConfs[prefix+name] = newConf
default:
return nil, nil, fmt.Errorf("proxy %s role should be 'server' or 'visitor'", name)
}
}
return proxyConfs, visitorConfs, nil
}
func renderRangeProxyTemplates(f *ini.File, section *ini.Section) error {
// Validation
localPortStr := section.Key("local_port").String()
remotePortStr := section.Key("remote_port").String()
if localPortStr == "" || remotePortStr == "" {
return fmt.Errorf("local_port or remote_port is empty")
}
localPorts, err := util.ParseRangeNumbers(localPortStr)
if err != nil {
return err
}
View on GitHub (pinned to 6c8a8d0a97)
Solutions
- Set role = server for exposing proxies or role = visitor for visitor sections, exact lowercase
- Remove the role key entirely for plain proxies (server is the default)
- Scan the config for stray whitespace or quotes around the role value
Example fix
; before [ssh] role = Server ; after (or just drop the key) [ssh] role = server
Defensive patterns
Strategy: validation
Validate before calling
role := section.Key("role").String()
if role != "" && role != "server" && role != "visitor" {
return fmt.Errorf("section %s: role must be 'server' or 'visitor'", section.Name())
} Type guard
func isValidRole(role string) bool { return role == "" || role == "server" || role == "visitor" } Prevention
- Omit role for normal proxies; set it only for visitors
- Use exact lowercase values
- Lint configs for unknown role values
When it happens
Trigger: A section with role = 'Server' (capitalized), 'srv', 'visit0r', or any string other than exactly 'server' or 'visitor'. Note the value is not trimmed beyond ini parsing, so trailing spaces also fail.
Common situations: Users upgrading from configs where role did not exist and guessing the value; case or spelling mistakes; copy-paste from docs of a different frp version that used different role names.
Related errors
- failed to parse proxy %s, err: %v
- local_port or remote_port is empty
- exec configuration is required when type is 'exec'
- file path cannot be empty
- exec command cannot be empty
AI-assisted analysis of fatedier/frp@6c8a8d0a97 (2026-08-15).
Data as JSON: /api/errors/19930d4edb0615c5.
Report an issue: GitHub.