{"record":{"id":"22ebf5c52bd6cf20","repo":"fatedier/frp","slug":"invalid-argument-visitor-name-in-url-must-match-n","errorCode":null,"errorMessage":"invalid argument: visitor name in URL must match name in body","messagePattern":"invalid argument: visitor name in URL must match name in body","errorType":"http","errorClass":"configmgmt.ErrInvalidArgument","httpStatus":400,"severity":"error","filePath":"client/config_manager.go","lineNumber":310,"sourceCode":"\t})\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\tlog.Infof(\"store: created visitor %q\", name)\n\treturn persisted, nil\n}\n\nfunc (m *serviceConfigManager) UpdateStoreVisitor(name string, cfg v1.VisitorConfigurer) (v1.VisitorConfigurer, error) {\n\tif name == \"\" {\n\t\treturn nil, fmt.Errorf(\"%w: visitor name is required\", configmgmt.ErrInvalidArgument)\n\t}\n\tif cfg == nil {\n\t\treturn nil, fmt.Errorf(\"%w: invalid visitor config: type is required\", configmgmt.ErrInvalidArgument)\n\t}\n\tbodyName := cfg.GetBaseConfig().Name\n\tif bodyName != name {\n\t\treturn nil, fmt.Errorf(\"%w: visitor name in URL must match name in body\", configmgmt.ErrInvalidArgument)\n\t}\n\tif err := m.validateStoreVisitorConfigurer(cfg); err != nil {\n\t\treturn nil, fmt.Errorf(\"%w: validation error: %v\", configmgmt.ErrInvalidArgument, err)\n\t}\n\n\tpersisted, err := m.withStoreVisitorMutationAndReload(name, func(storeSource *source.StoreSource) error {\n\t\tif err := storeSource.UpdateVisitor(cfg); err != nil {\n\t\t\tif errors.Is(err, source.ErrNotFound) {\n\t\t\t\treturn fmt.Errorf(\"%w: %v\", configmgmt.ErrNotFound, 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","sourceCodeStart":292,"sourceCodeEnd":328,"githubUrl":"https://github.com/fatedier/frp/blob/6c8a8d0a97d03b44e9528d30b30c70cb9d61b405/client/config_manager.go#L292-L328","documentation":"Thrown by frpc's config store API (UpdateStoreVisitor) when the visitor name in the URL path does not equal the name inside the request body's visitor config. The client enforces name consistency so an update request cannot silently rename a visitor. Maps to HTTP 400 via configmgmt.ErrInvalidArgument in client/http/controller.go.","triggerScenarios":"PUT /api/config/visitors/{name} (UpdateStoreVisitor) where body JSON's name field differs from the {name} path segment, e.g. path says 'ssh-visitor' but body contains \"name\": \"ssh-visitor-2\". Only reached when the store is enabled; cfg must be non-nil first.","commonSituations":"Automation scripts that generate the body from a template but build the URL from a stale variable; renaming a visitor by editing only the body or only the URL; copy-pasting a config and forgetting to sync both places.","solutions":["Make the URL name and the body name identical (pick the target name, set it in both places)","If you intend to rename, delete the old visitor (DELETE /api/config/visitors/{old}) and create a new one with the new name","In client code, derive both the URL segment and the body name from a single variable"],"exampleFix":"// before\nname := \"ssh-visitor\"\nurl := fmt.Sprintf(\"/api/config/visitors/%s\", name)\nbody.Name = \"ssh-visitor-2\" // mismatch\n\n// after\nname := \"ssh-visitor\"\nurl := fmt.Sprintf(\"/api/config/visitors/%s\", name)\nbody.Name = name // URL and body always derived from one source","handlingStrategy":"validation","validationCode":"func validVisitorUpdateRequest(urlName string, body []byte) error {\n\tvar partial struct{ Name string `json:\"name\"` }\n\tif err := json.Unmarshal(body, &partial); err != nil {\n\t\treturn fmt.Errorf(\"body is not valid visitor JSON: %w\", err)\n\t}\n\tif partial.Name == \"\" || partial.Name != urlName {\n\t\treturn fmt.Errorf(\"body name %q must match URL name %q\", partial.Name, urlName)\n\t}\n\treturn nil\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Derive URL path segment and body name from the same variable in client code","For renames, use delete-then-create instead of update","Assert on HTTP 400 responses as a config bug in your automation, not a runtime condition"],"tags":["frp","frpc","config-store","validation","api"],"backgroundTag":null,"analyzedSha":"6c8a8d0a97d03b44e9528d30b30c70cb9d61b405","analyzedAt":"2026-08-15T06:53:27.215Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}