fatedier/frp · error
failed to decode visitor at index %d: %w
Error message
failed to decode visitor at index %d: %w
What it means
The visitor analogue of the proxy decode error: DecodeVisitorConfigurerJSON failed for the i-th element of the visitors array in the store file. Either the "type" discriminator does not match a registered VisitorConfigurer type (stcp, xtcp, sudp) or the payload is structurally incompatible with that type.
Source
Thrown at pkg/config/source/store.go:113
proxyCfg, err := v1.DecodeProxyConfigurerJSON(proxyData, v1.DecodeOptions{
DisallowUnknownFields: false,
})
if err != nil {
return fmt.Errorf("failed to decode proxy at index %d: %w", i, err)
}
name := proxyCfg.GetBaseConfig().Name
if name == "" {
return fmt.Errorf("proxy name cannot be empty")
}
s.proxies[name] = proxyCfg
}
for i, visitorData := range stored.Visitors {
visitorCfg, err := v1.DecodeVisitorConfigurerJSON(visitorData, v1.DecodeOptions{
DisallowUnknownFields: false,
})
if err != nil {
return fmt.Errorf("failed to decode visitor at index %d: %w", i, err)
}
name := visitorCfg.GetBaseConfig().Name
if name == "" {
return fmt.Errorf("visitor name cannot be empty")
}
s.visitors[name] = visitorCfg
}
return nil
}
func (s *StoreSource) saveToFileUnlocked() error {
stored := storeData{
Proxies: make([]v1.TypedProxyConfig, 0, len(s.proxies)),
Visitors: make([]v1.TypedVisitorConfig, 0, len(s.visitors)),
}
for _, p := range s.proxies {View on GitHub (pinned to 6c8a8d0a97)
Solutions
- Check the visitors array element at the reported index in the store file
- Confirm "type" is a valid visitor type for the running frp version (stcp, xtcp, sudp)
- Upgrade frp if the entry was written by a newer release
- Fix the type field or remove the broken entry and retry
Example fix
// before (visitors[0])
{ "type": "stcp", "name": "ssh-visitor" }
// after (if "stcp" unknown to this build, upgrade; or fix e.g. wrong array)
{ "type": "stcp", "name": "ssh-visitor", "serverName": "ssh", "secretKey": "..." } Defensive patterns
Strategy: validation
Validate before calling
var supportedVisitorTypes = map[string]bool{"stcp": true, "xtcp": true, "sudp": true}
func validateVisitorTypes(path string) error {
data, _ := os.ReadFile(path)
var raw struct {
Visitors []json.RawMessage `json:"visitors"`
}
if json.Unmarshal(data, &raw) != nil {
return nil
}
for i, v := range raw.Visitors {
var t struct{ Type string `json:"type"` }
if json.Unmarshal(v, &t) != nil || !supportedVisitorTypes[t.Type] {
return fmt.Errorf("visitors[%d]: unsupported type %q", i, t.Type)
}
}
return nil
} Prevention
- Do not put proxy types (tcp/http/...) in the visitors array; only stcp/xtcp/sudp are visitors
- Keep frp versions consistent across writers and readers of the store file
- Validate machine-generated visitor entries with a schema check before deploy
When it happens
Trigger: A visitors entry with a misspelled/missing/unknown "type"; a store written by a newer frp containing visitor types the running build lacks; a payload field with the wrong JSON type for the target struct.
Common situations: Version downgrade after a newer frp wrote the store; hand-edited visitor entries; using a proxy type (e.g. "tcp") in the visitors array, which is not a visitor type.
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
- failed to decode proxy at index %d: %w
- visitor name cannot be empty
- unknown visitor type: %s
- unmarshal VisitorConfig error: %v
- unmarshal visitor plugin error: %v
AI-assisted analysis of fatedier/frp@6c8a8d0a97 (2026-08-15).
Data as JSON: /api/errors/cfbf23f5c6e4b2e4.
Report an issue: GitHub.