{"record":{"id":"a2b28fbe9762d5c6","repo":"fatedier/frp","slug":"invalid-proxy-type-s","errorCode":null,"errorMessage":"invalid proxy type: %s","messagePattern":"invalid proxy type: (.+?)","errorType":"validation","errorClass":null,"httpStatus":400,"severity":"error","filePath":"client/http/model/proxy_definition.go","lineNumber":29,"sourceCode":"\tName string `json:\"name\"`\n\tType string `json:\"type\"`\n\n\tTCP    *v1.TCPProxyConfig    `json:\"tcp,omitempty\"`\n\tUDP    *v1.UDPProxyConfig    `json:\"udp,omitempty\"`\n\tHTTP   *v1.HTTPProxyConfig   `json:\"http,omitempty\"`\n\tHTTPS  *v1.HTTPSProxyConfig  `json:\"https,omitempty\"`\n\tTCPMux *v1.TCPMuxProxyConfig `json:\"tcpmux,omitempty\"`\n\tSTCP   *v1.STCPProxyConfig   `json:\"stcp,omitempty\"`\n\tSUDP   *v1.SUDPProxyConfig   `json:\"sudp,omitempty\"`\n\tXTCP   *v1.XTCPProxyConfig   `json:\"xtcp,omitempty\"`\n}\n\nfunc (p *ProxyDefinition) Validate(pathName string, isUpdate bool) error {\n\tif strings.TrimSpace(p.Name) == \"\" {\n\t\treturn fmt.Errorf(\"proxy name is required\")\n\t}\n\tif !IsProxyType(p.Type) {\n\t\treturn fmt.Errorf(\"invalid proxy type: %s\", p.Type)\n\t}\n\tif isUpdate && pathName != \"\" && pathName != p.Name {\n\t\treturn fmt.Errorf(\"proxy name in URL must match name in body\")\n\t}\n\n\t_, blockType, blockCount := p.activeBlock()\n\tif blockCount != 1 {\n\t\treturn fmt.Errorf(\"exactly one proxy type block is required\")\n\t}\n\tif blockType != p.Type {\n\t\treturn fmt.Errorf(\"proxy type block %q does not match type %q\", blockType, p.Type)\n\t}\n\treturn nil\n}\n\nfunc (p *ProxyDefinition) ToConfigurer() (v1.ProxyConfigurer, error) {\n\tblock, _, _ := p.activeBlock()\n\tif block == nil {","sourceCodeStart":11,"sourceCodeEnd":47,"githubUrl":"https://github.com/fatedier/frp/blob/6c8a8d0a97d03b44e9528d30b30c70cb9d61b405/client/http/model/proxy_definition.go#L11-L47","documentation":"Returned by ProxyDefinition.Validate when the proxy definition's \"type\" string is not one of the eight supported proxy types (tcp, udp, http, https, tcpmux, stcp, sudp, xtcp). It is checked right after the name, so it fires even if a valid type block is present.","triggerScenarios":"POST/PUT /api/proxies with \"type\": \"HTTP\" (wrong case), \"type\": \"grpc\", a typo like \"tcpmux\" instead of \"tcpmux\", or a missing \"type\" field (empty string).","commonSituations":"Case mismatch (frp requires lowercase type strings); using a type introduced in a newer frp version against an older frpc; renaming a type in config after an upgrade; copying a v1 config into the admin API with the wrong casing.","solutions":["Set \"type\" to one of tcp, udp, http, https, tcpmux, stcp, sudp, xtcp — all lowercase.","Check for typos and trailing whitespace in the type field.","If you need a newer type, upgrade frpc/frps to a version that supports it."],"exampleFix":"// before\n{\"name\": \"ssh\", \"type\": \"TCP\", \"tcp\": {\"localPort\": 22}}\n\n// after\n{\"name\": \"ssh\", \"type\": \"tcp\", \"tcp\": {\"localPort\": 22}}","handlingStrategy":"validation","validationCode":"var proxyTypes = map[string]bool{\"tcp\":true,\"udp\":true,\"http\":true,\"https\":true,\"tcpmux\":true,\"stcp\":true,\"sudp\":true,\"xtcp\":true}\nfunc validProxyType(t string) bool { return proxyTypes[strings.ToLower(strings.TrimSpace(t))] }","typeGuard":"func isProxyType(t string) bool {\n    switch t {\n    case \"tcp\", \"udp\", \"http\", \"https\", \"tcpmux\", \"stcp\", \"sudp\", \"xtcp\":\n        return true\n    }\n    return false\n}","tryCatchPattern":"if !isProxyType(def.Type) { return fmt.Errorf(\"reject before send: bad type %q\", def.Type) }","preventionTips":["Derive the type string from the same constant used to pick the block.","Always lowercase type values.","Check frp docs/version for supported types before using new ones."],"tags":["api","validation","proxy-type","frpc-admin"],"backgroundTag":null,"analyzedSha":"6c8a8d0a97d03b44e9528d30b30c70cb9d61b405","analyzedAt":"2026-08-15T06:53:27.215Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}