fatedier/frp · error
failed to parse visitor %s, err: %v
Error message
failed to parse visitor %s, err: %v
What it means
Legacy ini loader counterpart of error 152: for a section with role = 'visitor', NewVisitorConfFromIni maps and validates it. Failures — missing required visitor fields (server_name, bind_port, secret_key for stcp/xtcp/sudp visitors), invalid ports, wrong type for a visitor — are wrapped with the section name.
Source
Thrown at pkg/config/legacy/client.go:279
continue
}
roleType := section.Key("role").String()
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)View on GitHub (pinned to 6c8a8d0a97)
Solutions
- Read the inner error to see which required key failed
- For stcp/xtcp visitors set: type, server_name (the exposed proxy's name), secret_key, bind_port, and role = visitor
- Ensure bind_port is a valid integer on the visitor host
- Confirm the exposing side and visitor share the same secret_key and server_name
Example fix
; before [secret_visor] role = visitor type = stcp server_name = secret-http bind_port = 8080 ; missing secret_key ; after [secret_visor] role = visitor type = stcp server_name = secret-http secret_key = "abcdef" bind_port = 8080
Defensive patterns
Strategy: validation
Validate before calling
required := []string{"server_name", "bind_port"}
if section.Key("type").String() != "http" { /* stcp/xtcp/sudp visitors also need secret_key */ }
for _, k := range required {
if section.Key(k).String() == "" {
return fmt.Errorf("visitor %s missing %s", section.Name(), k)
}
} Prevention
- Template visitor sections with role/type/server_name/secret_key/bind_port pre-filled
- Keep secret_key identical on expose and visitor sides
- Test visitor configs with frpc verify before rollout
When it happens
Trigger: A [role = visitor] section for an stcp/xtcp/sudp proxy that omits server_name or secret_key, sets a non-numeric bind_port, or uses a type that does not support visitors (http/https/tcpmux).
Common situations: Setting up an stcp visitor and copying the server-side section without renaming keys; forgetting that visitors reference the exposing proxy by server_name, not proxy name; bind_port conflicts noted as invalid values.
Understand the failure class
- Parsing and encoding errors: unexpected token, malformed input — why parsers reject input and how to find the real culprit.
Related errors
- visitor %s: %v
- server name is required
- destinationIP is required
- invalid configuration file, not found [common] section
- failed to render template for proxy %s: %v
AI-assisted analysis of fatedier/frp@6c8a8d0a97 (2026-08-15).
Data as JSON: /api/errors/6b2abd9776e7ffac.
Report an issue: GitHub.