{"record":{"id":"3c638a8662c09482","repo":"fatedier/frp","slug":"server-name-is-required","errorCode":null,"errorMessage":"server name is required","messagePattern":"server name is required","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/config/v1/validation/visitor.go","lineNumber":48,"sourceCode":"\n\tswitch v := c.(type) {\n\tcase *v1.STCPVisitorConfig:\n\tcase *v1.SUDPVisitorConfig:\n\tcase *v1.XTCPVisitorConfig:\n\t\treturn validateXTCPVisitorConfig(v)\n\tdefault:\n\t\treturn errors.New(\"unknown visitor config type\")\n\t}\n\treturn nil\n}\n\nfunc validateVisitorBaseConfig(c *v1.VisitorBaseConfig) error {\n\tif c.Name == \"\" {\n\t\treturn errors.New(\"name is required\")\n\t}\n\n\tif c.ServerName == \"\" {\n\t\treturn errors.New(\"server name is required\")\n\t}\n\n\tif c.BindPort == 0 {\n\t\treturn errors.New(\"bind port is required\")\n\t}\n\treturn nil\n}\n\nfunc validateXTCPVisitorConfig(c *v1.XTCPVisitorConfig) error {\n\tif !slices.Contains([]string{\"kcp\", \"quic\"}, c.Protocol) {\n\t\treturn fmt.Errorf(\"protocol should be kcp or quic\")\n\t}\n\treturn nil\n}\n","sourceCodeStart":30,"sourceCodeEnd":63,"githubUrl":"https://github.com/fatedier/frp/blob/6c8a8d0a97d03b44e9528d30b30c70cb9d61b405/pkg/config/v1/validation/visitor.go#L30-L63","documentation":"Validation error from validateVisitorBaseConfig: a visitor entry has an empty serverName. The serverName tells frpc which exported secret/p2p proxy (the server-side peer's proxy name) to connect to via frps; without it the visitor cannot identify its target. Second mandatory check in visitor base validation.","triggerScenarios":"A [[visitors]] entry missing serverName or with serverName = \"\". Common when the author confuses serverName (peer proxy name) with the frps server address (serverAddr) and omits it.","commonSituations":"First-time visitor configs assuming serverName is the frps host; copying the proxy's name field incorrectly; whitespace-only value after editing; programmatic construction skipping VisitorBaseConfig.ServerName.","solutions":["Set serverName = \"<name of the stcp/sudp/xtcp proxy on the server side>\" — it must equal that proxy's name exactly, including case.","Do not put the frps address here; that belongs to serverAddr at the client top level.","Verify the matching proxy is actually running and reachable, and that secretKey matches it."],"exampleFix":"# before\n[[visitors]]\nname = \"v\"\ntype = \"stcp\"\nsecretKey = \"s\"\nbindAddr = \"127.0.0.1\"\nbindPort = 9000\n\n# after\n[[visitors]]\nname = \"v\"\ntype = \"stcp\"\nserverName = \"stcp-srv\"\nsecretKey = \"s\"\nbindAddr = \"127.0.0.1\"\nbindPort = 9000","handlingStrategy":"validation","validationCode":"base := v.GetBaseConfig()\nif base == nil || base.ServerName == \"\" {\n    return errors.New(\"visitor requires serverName equal to the server-side proxy name\")\n}","typeGuard":"func visitorTargetSet(c v1.VisitorConfigurer) bool {\n    base := c.GetBaseConfig()\n    return c != nil && base != nil && base.ServerName != \"\"\n}","tryCatchPattern":"if err := validation.ValidateVisitorConfigurer(v); err != nil {\n    if strings.Contains(err.Error(), \"server name is required\") {\n        // set serverName to the stcp/sudp/xtcp proxy name on the other side\n    }\n    return err\n}","preventionTips":["serverName is the peer proxy's name, not the frps address.","Keep the proxy name and its visitor serverName in one shared config doc.","Match secretKey on both sides at the same time."],"tags":["config","visitor","validation","frpc","stcp"],"backgroundTag":null,"analyzedSha":"6c8a8d0a97d03b44e9528d30b30c70cb9d61b405","analyzedAt":"2026-08-15T06:53:27.215Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}