{"record":{"id":"cfcd960fbd1cd01c","repo":"fatedier/frp","slug":"name-should-not-be-empty","errorCode":null,"errorMessage":"name should not be empty","messagePattern":"name should not be empty","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/config/v1/validation/proxy.go","lineNumber":30,"sourceCode":"// See the License for the specific language governing permissions and\n// limitations under the License.\n\npackage validation\n\nimport (\n\t\"errors\"\n\t\"fmt\"\n\t\"slices\"\n\t\"strings\"\n\n\t\"k8s.io/apimachinery/pkg/util/validation\"\n\n\tv1 \"github.com/fatedier/frp/pkg/config/v1\"\n)\n\nfunc validateProxyBaseConfigForClient(c *v1.ProxyBaseConfig) error {\n\tif c.Name == \"\" {\n\t\treturn errors.New(\"name should not be empty\")\n\t}\n\n\tif err := ValidateAnnotations(c.Annotations); err != nil {\n\t\treturn err\n\t}\n\tif !slices.Contains([]string{\"\", \"v1\", \"v2\"}, c.Transport.ProxyProtocolVersion) {\n\t\treturn fmt.Errorf(\"not support proxy protocol version: %s\", c.Transport.ProxyProtocolVersion)\n\t}\n\tif !slices.Contains([]string{\"client\", \"server\"}, c.Transport.BandwidthLimitMode) {\n\t\treturn fmt.Errorf(\"bandwidth limit mode should be client or server\")\n\t}\n\n\tif c.Plugin.Type == \"\" {\n\t\tif err := ValidatePort(c.LocalPort, \"localPort\"); err != nil {\n\t\t\treturn fmt.Errorf(\"localPort: %v\", err)\n\t\t}\n\t}\n","sourceCodeStart":12,"sourceCodeEnd":48,"githubUrl":"https://github.com/fatedier/frp/blob/6c8a8d0a97d03b44e9528d30b30c70cb9d61b405/pkg/config/v1/validation/proxy.go#L12-L48","documentation":"Validation error from validateProxyBaseConfigForClient: a proxy entry in the frpc config has an empty Name. Every proxy must be uniquely named so frps can route and manage it (the name becomes the proxy identity reported to the server). This is the first check run by ValidateProxyConfigurerForClient on the proxy's base config.","triggerScenarios":"A [[proxies]] entry in frpc TOML/JSON/YAML that omits the name field, sets name = \"\", or whose keys failed to decode so the base config is zero-valued. Also triggered programmatically when constructing a ProxyConfigurer without setting BaseConfig.Name.","commonSituations":"Copying a template proxy block and deleting the name; TOML table-name typos making the whole entry decode to defaults; programmatic config builders that forget Name; duplicate-table syntax overriding a named entry with an unnamed one.","solutions":["Add a non-empty, unique name = \"my-proxy\" to each [[proxies]] entry.","Ensure names are unique across all proxies in one frpc config — duplicates cause server-side rejection even after this check passes.","If generating configs in Go, always set cfg.GetBaseConfig().Name before validation."],"exampleFix":"# before\n[[proxies]]\ntype = \"tcp\"\nremotePort = 6000\n\n# after\n[[proxies]]\nname = \"ssh\"\ntype = \"tcp\"\nremotePort = 6000","handlingStrategy":"validation","validationCode":"for _, p := range clientCfg.Proxies {\n    if p.GetBaseConfig() == nil || p.GetBaseConfig().Name == \"\" {\n        return errors.New(\"every proxy needs a non-empty unique name\")\n    }\n}","typeGuard":"func proxyNameSet(c v1.ProxyConfigurer) bool {\n    base := c.GetBaseConfig()\n    return c != nil && base != nil && base.Name != \"\"\n}","tryCatchPattern":"if err := validation.ValidateProxyConfigurerForClient(p); err != nil {\n    if strings.Contains(err.Error(), \"name should not be empty\") {\n        // give the [[proxies]] entry a name\n    }\n    return err\n}","preventionTips":["Every [[proxies]] entry starts with name in your template.","Keep proxy names unique across the config.","Lint configs in CI with frpc verify."],"tags":["config","proxy","validation","frpc","naming"],"backgroundTag":null,"analyzedSha":"6c8a8d0a97d03b44e9528d30b30c70cb9d61b405","analyzedAt":"2026-08-15T06:53:27.215Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}