{"record":{"id":"2a3b2a1aa823544a","repo":"fatedier/frp","slug":"invalid-argument-validation-error-v","errorCode":null,"errorMessage":"invalid argument: validation error: %v","messagePattern":"invalid argument: validation error: (.+?)","errorType":"http","errorClass":"configmgmt.ErrInvalidArgument","httpStatus":400,"severity":"error","filePath":"client/config_manager.go","lineNumber":180,"sourceCode":"\tif name == \"\" {\n\t\treturn nil, fmt.Errorf(\"%w: proxy name is required\", configmgmt.ErrInvalidArgument)\n\t}\n\n\tstoreSource, err := m.storeSourceOrError()\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\tcfg := storeSource.GetProxy(name)\n\tif cfg == nil {\n\t\treturn nil, fmt.Errorf(\"%w: proxy %q\", configmgmt.ErrNotFound, name)\n\t}\n\treturn cfg, nil\n}\n\nfunc (m *serviceConfigManager) CreateStoreProxy(cfg v1.ProxyConfigurer) (v1.ProxyConfigurer, error) {\n\tif err := m.validateStoreProxyConfigurer(cfg); err != nil {\n\t\treturn nil, fmt.Errorf(\"%w: validation error: %v\", configmgmt.ErrInvalidArgument, err)\n\t}\n\n\tname := cfg.GetBaseConfig().Name\n\tpersisted, err := m.withStoreProxyMutationAndReload(name, func(storeSource *source.StoreSource) error {\n\t\tif err := storeSource.AddProxy(cfg); err != nil {\n\t\t\tif errors.Is(err, source.ErrAlreadyExists) {\n\t\t\t\treturn fmt.Errorf(\"%w: %v\", configmgmt.ErrConflict, err)\n\t\t\t}\n\t\t\treturn err\n\t\t}\n\t\treturn nil\n\t})\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\tlog.Infof(\"store: created proxy %q\", name)\n\treturn persisted, nil\n}","sourceCodeStart":162,"sourceCodeEnd":198,"githubUrl":"https://github.com/fatedier/frp/blob/6c8a8d0a97d03b44e9528d30b30c70cb9d61b405/client/config_manager.go#L162-L198","documentation":"Returned by CreateStoreProxy when validateStoreProxyConfigurer rejects the submitted proxy config before anything is persisted. The wrapped validation error details the actual problem (missing/invalid name, missing type, invalid port ranges, invalid plugin fields, etc.). It maps to HTTP 400 via configmgmt.ErrInvalidArgument.","triggerScenarios":"POST /api/store/proxies with a body missing required fields for the proxy type (e.g. a tcp proxy without remotePort), an invalid or empty name, unsupported type value, or a plugin block that fails validation. Also triggered by structurally valid JSON whose field values violate v1 validation rules.","commonSituations":"Switching proxy type and forgetting type-specific fields (udp needs nothing extra, tcp needs remotePort); typos in the type discriminator; submitting YAML-shaped keys to a JSON/TOML endpoint; port values outside 1-65535 or colliding localPort semantics.","solutions":["Read the wrapped validation message; it names the exact field and rule that failed.","Compare your body against a known-good proxy via GET /api/store/proxies and mirror the required fields.","Ensure 'name' is set, 'type' is one of the supported types (tcp/udp/http/https/tcpmux/stcp/sudp/xtcp), and type-specific fields (remotePort, subdomain, locations, secretKey...) are present.","Validate locally with the same v1 validation package before posting if you drive the Go API directly."],"exampleFix":"# before (missing remotePort for tcp)\ncurl -X POST http://127.0.0.1:7400/api/store/proxies \\\n  -d '{\"type\":\"tcp\",\"name\":\"ssh\",\"localPort\":22}'\n# invalid argument: validation error: remotePort required\n\n# after\ncurl -X POST http://127.0.0.1:7400/api/store/proxies \\\n  -d '{\"type\":\"tcp\",\"name\":\"ssh\",\"localPort\":22,\"remotePort\":6022}'","handlingStrategy":"validation","validationCode":"// Mirror required fields before POST.\nbody := map[string]any{\"type\": \"tcp\", \"name\": name, \"localPort\": lp, \"remotePort\": rp}\nif name == \"\" || body[\"type\"] == \"\" || lp <= 0 || rp <= 0 {\n    return errors.New(\"proxy payload incomplete\")\n}","typeGuard":null,"tryCatchPattern":"if _, err := mgr.CreateStoreProxy(cfg); err != nil {\n    if errors.Is(err, configmgmt.ErrInvalidArgument) {\n        // err text carries the validation detail; fix the offending field\n    }\n}","preventionTips":["Round-trip a known-good proxy from GET as your template","Log full error text — validation messages name the exact failing field"],"tags":["frp","frpc","store","proxy","validation"],"backgroundTag":null,"analyzedSha":"6c8a8d0a97d03b44e9528d30b30c70cb9d61b405","analyzedAt":"2026-08-15T06:53:27.215Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}