{"record":{"id":"e731de6548e4aa9a","repo":"fatedier/frp","slug":"proxy-name-cannot-be-empty-e731de","errorCode":null,"errorMessage":"proxy name cannot be empty","messagePattern":"proxy name cannot be empty","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"pkg/config/source/validation.go","lineNumber":29,"sourceCode":"// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\npackage source\n\nimport (\n\t\"fmt\"\n\n\tv1 \"github.com/fatedier/frp/pkg/config/v1\"\n)\n\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":11,"sourceCodeEnd":44,"githubUrl":"https://github.com/fatedier/frp/blob/6c8a8d0a97d03b44e9528d30b30c70cb9d61b405/pkg/config/source/validation.go#L11-L44","documentation":"validateProxyName rejected a proxy passed to AddProxy or UpdateProxy because its base config Name is empty (a nil proxy is a separate error). Every proxy must be named before entering the store, since the name is the map key and the persistence identity.","triggerScenarios":"store.AddProxy(&v1.TCPProxyConfig{...}) where the embedded ProxyBaseConfig.Name was never set; building a configurer via struct literal and forgetting the Name field; copying a template config without filling the name.","commonSituations":"Programmatic proxy registration code that constructs configs in loops with a name variable that ended up empty; parsing user input where the name field was optional and left blank.","solutions":["Set a unique non-empty name on the base config before calling Add/Update","If the name comes from user input, validate it server-side before constructing the configurer","Log the offending entry when validation fails so the source of the empty name is findable"],"exampleFix":"// before\ncfg := &v1.TCPProxyConfig{LocalPort: 22}\nerr := store.AddProxy(cfg) // proxy name cannot be empty\n\n// after\ncfg := &v1.TCPProxyConfig{ProxyBaseConfig: v1.ProxyBaseConfig{Name: \"ssh\"}, LocalPort: 22}\nerr := store.AddProxy(cfg)","handlingStrategy":"validation","validationCode":"func namedProxy(cfg *v1.TCPProxyConfig) *v1.TCPProxyConfig {\n\tif strings.TrimSpace(cfg.Name) == \"\" {\n\t\tcfg.Name = fmt.Sprintf(\"tcp-%d\", cfg.LocalPort)\n\t}\n\treturn cfg\n}\n\n// or generic pre-check before Add:\nif cfg.GetBaseConfig().Name == \"\" { return errors.New(\"proxy name required\") }","typeGuard":"func hasProxyName(p v1.ProxyConfigurer) bool {\n\treturn p != nil && strings.TrimSpace(p.GetBaseConfig().Name) != \"\"\n}","tryCatchPattern":null,"preventionTips":["Centralize proxy construction in one factory that always assigns a name","Validate user-supplied names as required input at the edge (HTTP schema, CLI flag required)","Add unit tests asserting every programmatically built proxy has a non-empty name"],"tags":["validation","required-field","caller-error","go"],"backgroundTag":null,"analyzedSha":"6c8a8d0a97d03b44e9528d30b30c70cb9d61b405","analyzedAt":"2026-08-15T06:53:27.215Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}