{"record":{"id":"d1c5ffa6a575d01b","repo":"fatedier/frp","slug":"invalid-visitor-config","errorCode":null,"errorMessage":"invalid visitor config","messagePattern":"invalid visitor config","errorType":"validation","errorClass":null,"httpStatus":400,"severity":"error","filePath":"client/config_manager.go","lineNumber":456,"sourceCode":"\t}\n\treturn persisted.Clone(), nil\n}\n\nfunc (m *serviceConfigManager) validateStoreProxyConfigurer(cfg v1.ProxyConfigurer) error {\n\tif cfg == nil {\n\t\treturn fmt.Errorf(\"invalid proxy config\")\n\t}\n\truntimeCfg := cfg.Clone()\n\tif runtimeCfg == nil {\n\t\treturn fmt.Errorf(\"invalid proxy config\")\n\t}\n\truntimeCfg.Complete()\n\treturn validation.ValidateProxyConfigurerForClient(runtimeCfg)\n}\n\nfunc (m *serviceConfigManager) validateStoreVisitorConfigurer(cfg v1.VisitorConfigurer) error {\n\tif cfg == nil {\n\t\treturn fmt.Errorf(\"invalid visitor config\")\n\t}\n\truntimeCfg := cfg.Clone()\n\tif runtimeCfg == nil {\n\t\treturn fmt.Errorf(\"invalid visitor config\")\n\t}\n\truntimeCfg.Complete()\n\treturn validation.ValidateVisitorConfigurer(runtimeCfg)\n}\n","sourceCodeStart":438,"sourceCodeEnd":465,"githubUrl":"https://github.com/fatedier/frp/blob/6c8a8d0a97d03b44e9528d30b30c70cb9d61b405/client/config_manager.go#L438-L465","documentation":"validateStoreVisitorConfigurer rejects a nil VisitorConfigurer before validation. Reached from CreateStoreVisitor/UpdateStoreVisitor when the decoded body has no usable visitor config — usually an unknown visitor type string. The caller sees 'invalid argument: validation error: invalid visitor config' (or the create-path equivalent).","triggerScenarios":"POST/PUT /api/config/visitors with a type the decoder does not recognize (valid: stcp, xtcp, sudp) or an empty body.","commonSituations":"Sending 'tcp' (a proxy type) as a visitor type; typos; using a visitor type added in a newer frp version than the running client.","solutions":["Use a valid visitor type: stcp, xtcp, or sudp","Include the base fields: name, bindPort, and the secretKey/serverName as required","Verify frpc version supports the visitor type"],"exampleFix":"// before\n{\"type\": \"tcp\", \"name\": \"v1\"}\n\n// after\n{\"type\": \"stcp\", \"name\": \"v1\", \"serverName\": \"svc\", \"secretKey\": \"k\", \"bindPort\": 6000}","handlingStrategy":"type-guard","validationCode":"func knownVisitorType(t string) bool {\n\tswitch t {\n\tcase \"stcp\", \"xtcp\", \"sudp\":\n\t\treturn true\n\t}\n\treturn false\n}","typeGuard":"func isValidVisitorBody(body []byte) bool {\n\tvar v struct{ Type string `json:\"type\"` }\n\tif json.Unmarshal(body, &v) != nil {\n\t\treturn false\n\t}\n\treturn knownVisitorType(v.Type)\n}","tryCatchPattern":null,"preventionTips":["Only stcp/xtcp/sudp are visitor types; tcp/http etc. are proxy types","Match frpc version to the visitor types you use"],"tags":["frp","frpc","config-store","validation","visitor"],"backgroundTag":null,"analyzedSha":"6c8a8d0a97d03b44e9528d30b30c70cb9d61b405","analyzedAt":"2026-08-15T06:53:27.215Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}