{"record":{"id":"1fe7b7726fe7859d","repo":"fatedier/frp","slug":"invalid-proxy-config","errorCode":null,"errorMessage":"invalid proxy config","messagePattern":"invalid proxy config","errorType":"validation","errorClass":null,"httpStatus":400,"severity":"error","filePath":"client/config_manager.go","lineNumber":444,"sourceCode":"\t}\n\n\tif err := fn(storeSource); err != nil {\n\t\treturn nil, err\n\t}\n\tif err := m.svr.reloadConfigFromSourcesLocked(); err != nil {\n\t\treturn nil, fmt.Errorf(\"%w: failed to apply config: %v\", configmgmt.ErrApplyConfig, err)\n\t}\n\n\tpersisted := storeSource.GetVisitor(name)\n\tif persisted == nil {\n\t\treturn nil, fmt.Errorf(\"%w: visitor %q not found in store after mutation\", configmgmt.ErrApplyConfig, name)\n\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()","sourceCodeStart":426,"sourceCodeEnd":462,"githubUrl":"https://github.com/fatedier/frp/blob/6c8a8d0a97d03b44e9528d30b30c70cb9d61b405/client/config_manager.go#L426-L462","documentation":"validateStoreProxyConfigurer rejects a nil ProxyConfigurer (or a config whose Clone() returns nil) before validation runs. In practice reached through CreateStoreProxy/UpdateStoreProxy where the decoded body produced a nil configurer — e.g. an unknown proxy type in the JSON payload. Surfaces as 'invalid argument: validation error: invalid proxy config' to the caller.","triggerScenarios":"POST/PUT /api/config/proxies with a JSON body whose type field is not a known proxy type (tcp/udp/http/https/stcp/sudp/xtcp/tcpmux), so decoding yields a nil configurer; or an empty body.","commonSituations":"Typos in the type field; sending a visitor config to the proxy endpoint; version mismatch where the server build lacks a newer proxy type.","solutions":["Set a valid type in the body (one of tcp, udp, http, https, stcp, sudp, xtcp, tcpmux)","Confirm you are posting to /api/config/proxies and not the visitors endpoint","Check the frp version supports that proxy type"],"exampleFix":"// before\n{\"type\": \"tcp-proxy\", \"name\": \"p1\", ...}\n\n// after\n{\"type\": \"tcp\", \"name\": \"p1\", \"localPort\": 22, \"remotePort\": 6022}","handlingStrategy":"type-guard","validationCode":"func knownProxyType(t string) bool {\n\tswitch t {\n\tcase \"tcp\", \"udp\", \"http\", \"https\", \"stcp\", \"sudp\", \"xtcp\", \"tcpmux\":\n\t\treturn true\n\t}\n\treturn false\n}","typeGuard":"func isValidProxyBody(body []byte) bool {\n\tvar p struct{ Type string `json:\"type\"` }\n\tif json.Unmarshal(body, &p) != nil {\n\t\treturn false\n\t}\n\treturn knownProxyType(p.Type)\n}","tryCatchPattern":null,"preventionTips":["Validate the type field against the supported set before posting","Post proxies to /api/config/proxies and visitors to /api/config/visitors"],"tags":["frp","frpc","config-store","validation","proxy"],"backgroundTag":null,"analyzedSha":"6c8a8d0a97d03b44e9528d30b30c70cb9d61b405","analyzedAt":"2026-08-15T06:53:27.215Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}