{"record":{"id":"2da5707ca032368a","repo":"fatedier/frp","slug":"visitor-name-cannot-be-empty-2da570","errorCode":null,"errorMessage":"visitor name cannot be empty","messagePattern":"visitor name cannot be empty","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"pkg/config/source/validation.go","lineNumber":40,"sourceCode":"\nfunc validateProxyName(proxy v1.ProxyConfigurer) (string, error) {\n\tif proxy == nil {\n\t\treturn \"\", fmt.Errorf(\"proxy cannot be nil\")\n\t}\n\tname := proxy.GetBaseConfig().Name\n\tif name == \"\" {\n\t\treturn \"\", fmt.Errorf(\"proxy name cannot be empty\")\n\t}\n\treturn name, nil\n}\n\nfunc validateVisitorName(visitor v1.VisitorConfigurer) (string, error) {\n\tif visitor == nil {\n\t\treturn \"\", fmt.Errorf(\"visitor cannot be nil\")\n\t}\n\tname := visitor.GetBaseConfig().Name\n\tif name == \"\" {\n\t\treturn \"\", fmt.Errorf(\"visitor name cannot be empty\")\n\t}\n\treturn name, nil\n}\n","sourceCodeStart":22,"sourceCodeEnd":44,"githubUrl":"https://github.com/fatedier/frp/blob/6c8a8d0a97d03b44e9528d30b30c70cb9d61b405/pkg/config/source/validation.go#L22-L44","documentation":"validateVisitorName rejected a visitor passed to AddVisitor or UpdateVisitor because its base config Name is empty (a nil visitor is a separate error). Visitors are keyed by name in the store, so an empty name can never be accepted.","triggerScenarios":"store.AddVisitor(&v1.STCPVisitorConfig{...}) without setting the embedded VisitorBaseConfig.Name; generating visitors from a config template where the name field was skipped for one item.","commonSituations":"Visitor registration loops with an empty name variable; migrating configs where names were derived from another field that was itself empty.","solutions":["Set a unique non-empty Name in the VisitorBaseConfig before Add/Update","Validate derived names (e.g. from serverName + suffix) are non-empty before constructing","Add unit tests that assert every generated visitor carries a name"],"exampleFix":"// before\ncfg := &v1.STCPVisitorConfig{ServerName: \"ssh\"}\nerr := store.AddVisitor(cfg) // visitor name cannot be empty\n\n// after\ncfg := &v1.STCPVisitorConfig{VisitorBaseConfig: v1.VisitorBaseConfig{Name: \"ssh-v\"}, ServerName: \"ssh\"}\nerr := store.AddVisitor(cfg)","handlingStrategy":"validation","validationCode":"func namedVisitor(cfg *v1.STCPVisitorConfig) *v1.STCPVisitorConfig {\n\tif strings.TrimSpace(cfg.Name) == \"\" {\n\t\tcfg.Name = cfg.ServerName + \"-visitor\"\n\t}\n\treturn cfg\n}","typeGuard":"func hasVisitorName(v v1.VisitorConfigurer) bool {\n\treturn v != nil && strings.TrimSpace(v.GetBaseConfig().Name) != \"\"\n}","tryCatchPattern":null,"preventionTips":["Derive visitor names from serverName by convention and assert non-empty in the builder","Treat visitor name as required in any request schema that creates visitors","Round-trip test visitor creation: add, reload store from disk, confirm names persist"],"tags":["validation","required-field","visitor","caller-error","go"],"backgroundTag":null,"analyzedSha":"6c8a8d0a97d03b44e9528d30b30c70cb9d61b405","analyzedAt":"2026-08-15T06:53:27.215Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}