{"record":{"id":"b4b8c969f3602edb","repo":"fatedier/frp","slug":"unknown-visitor-config-type","errorCode":null,"errorMessage":"unknown visitor config type","messagePattern":"unknown visitor config type","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/config/v1/validation/visitor.go","lineNumber":37,"sourceCode":"\t\"fmt\"\n\t\"slices\"\n\n\tv1 \"github.com/fatedier/frp/pkg/config/v1\"\n)\n\nfunc ValidateVisitorConfigurer(c v1.VisitorConfigurer) error {\n\tbase := c.GetBaseConfig()\n\tif err := validateVisitorBaseConfig(base); err != nil {\n\t\treturn err\n\t}\n\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}","sourceCodeStart":19,"sourceCodeEnd":55,"githubUrl":"https://github.com/fatedier/frp/blob/6c8a8d0a97d03b44e9528d30b30c70cb9d61b405/pkg/config/v1/validation/visitor.go#L19-L55","documentation":"Error from ValidateVisitorConfigurer: the visitor configurer is not one of *v1.STCPVisitorConfig, *v1.SUDPVisitorConfig, or *v1.XTCPVisitorConfig. Visitors exist only for the secret/p2p proxy types (stcp, sudp, xtcp); any other concrete type — or a nil interface — falls through to this default error after base validation. Usually a programmatic/embedding issue since file configs reject unknown visitor types at decode time.","triggerScenarios":"Calling validation.ValidateVisitorConfigurer(c) with a nil visitor configurer, a custom struct implementing VisitorConfigurer, or a value (not pointer) of a visitor config that no longer matches the case types.","commonSituations":"Embedding frp as a library and constructing visitor configs of the wrong type or leaving them nil; mixed library versions where the visitor type set differs; copying example code that validates a visitor for a proxy type that has no visitor support (e.g. tcp).","solutions":["Use one of the three supported visitor configurers: *v1.STCPVisitorConfig, *v1.SUDPVisitorConfig, *v1.XTCPVisitorConfig.","Guard against nil before validating: if c == nil { ... }.","Verify you are pairing the visitor with a matching stcp/sudp/xtcp proxy — tcp/udp/http proxies have no visitors."],"exampleFix":"// before\nvar vc v1.VisitorConfigurer\nerr := validation.ValidateVisitorConfigurer(vc)\n\n// after\nvc := &v1.STCPVisitorConfig{\n    VisitorBaseConfig: &v1.VisitorBaseConfig{\n        Name: \"stcpv\", ServerName: \"stcp-srv\", BindPort: 9000,\n    },\n    SecretKey: \"secret\",\n}\nerr := validation.ValidateVisitorConfigurer(vc)","handlingStrategy":"type-guard","validationCode":"func isKnownVisitorType(c v1.VisitorConfigurer) bool {\n    switch c.(type) {\n    case *v1.STCPVisitorConfig, *v1.SUDPVisitorConfig, *v1.XTCPVisitorConfig:\n        return true\n    }\n    return false\n}","typeGuard":"func isKnownVisitorType(c v1.VisitorConfigurer) bool {\n    switch c.(type) {\n    case *v1.STCPVisitorConfig, *v1.SUDPVisitorConfig, *v1.XTCPVisitorConfig:\n        return true\n    default:\n        return false\n    }\n}","tryCatchPattern":"if !isKnownVisitorType(cfg) {\n    return fmt.Errorf(\"unsupported visitor configurer %T\", cfg)\n}\nif err := validation.ValidateVisitorConfigurer(cfg); err != nil { return err }","preventionTips":["Only stcp/sudp/xtcp have visitors — do not build visitors for tcp/udp/http.","Nil-check visitor configs before validating.","Keep the frp library version aligned with the visitor types you construct."],"tags":["go-api","visitor","validation","type-switch","stcp"],"backgroundTag":null,"analyzedSha":"6c8a8d0a97d03b44e9528d30b30c70cb9d61b405","analyzedAt":"2026-08-15T06:53:27.215Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}