{"record":{"id":"92b1821be90fba6d","repo":"fatedier/frp","slug":"visitor-name-in-url-must-match-name-in-body","errorCode":null,"errorMessage":"visitor name in URL must match name in body","messagePattern":"visitor name in URL must match name in body","errorType":"http","errorClass":null,"httpStatus":400,"severity":"error","filePath":"client/http/model/visitor_definition.go","lineNumber":27,"sourceCode":"\ntype VisitorDefinition struct {\n\tName string `json:\"name\"`\n\tType string `json:\"type\"`\n\n\tSTCP *v1.STCPVisitorConfig `json:\"stcp,omitempty\"`\n\tSUDP *v1.SUDPVisitorConfig `json:\"sudp,omitempty\"`\n\tXTCP *v1.XTCPVisitorConfig `json:\"xtcp,omitempty\"`\n}\n\nfunc (p *VisitorDefinition) Validate(pathName string, isUpdate bool) error {\n\tif strings.TrimSpace(p.Name) == \"\" {\n\t\treturn fmt.Errorf(\"visitor name is required\")\n\t}\n\tif !IsVisitorType(p.Type) {\n\t\treturn fmt.Errorf(\"invalid visitor type: %s\", p.Type)\n\t}\n\tif isUpdate && pathName != \"\" && pathName != p.Name {\n\t\treturn fmt.Errorf(\"visitor name in URL must match name in body\")\n\t}\n\n\t_, blockType, blockCount := p.activeBlock()\n\tif blockCount != 1 {\n\t\treturn fmt.Errorf(\"exactly one visitor type block is required\")\n\t}\n\tif blockType != p.Type {\n\t\treturn fmt.Errorf(\"visitor type block %q does not match type %q\", blockType, p.Type)\n\t}\n\treturn nil\n}\n\nfunc (p *VisitorDefinition) ToConfigurer() (v1.VisitorConfigurer, error) {\n\tblock, _, _ := p.activeBlock()\n\tif block == nil {\n\t\treturn nil, fmt.Errorf(\"exactly one visitor type block is required\")\n\t}\n","sourceCodeStart":9,"sourceCodeEnd":45,"githubUrl":"https://github.com/fatedier/frp/blob/6c8a8d0a97d03b44e9528d30b30c70cb9d61b405/client/http/model/visitor_definition.go#L9-L45","documentation":"Returned by VisitorDefinition.Validate during a visitor update (PUT /api/visitors/{name}) when the name in the URL path differs from the body's \"name\". Like proxies, visitors cannot be renamed in place; the identity in the path and body must match.","triggerScenarios":"PUT /api/visitors/old-v with body {\"name\":\"new-v\", ...}; any update where pathName is non-empty and differs from the body name.","commonSituations":"Regenerating the body with a new name while the client library still targets the old URL; attempting rename via PUT; reusing a stored payload for a different visitor.","solutions":["Set the body \"name\" to the same value as the URL path name.","To rename, delete the visitor and create a new one.","Assert body.name == URL name in client code before issuing the PUT."],"exampleFix":"// before\nPUT /api/visitors/visitor-a\n{\"name\": \"visitor-b\", \"type\": \"stcp\", ...}\n\n// after\nPUT /api/visitors/visitor-a\n{\"name\": \"visitor-a\", \"type\": \"stcp\", ...}","handlingStrategy":"validation","validationCode":"func checkVisitorNameMatch(pathName string, body map[string]any) error {\n    name, _ := body[\"name\"].(string)\n    if pathName != \"\" && name != pathName { return fmt.Errorf(\"body name %q != URL name %q\", name, pathName) }\n    return nil\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Build URL and body name from one variable.","Rename = delete + create, never PUT with a changed name.","Assert equality before sending updates."],"tags":["api","validation","update","frpc-admin"],"backgroundTag":null,"analyzedSha":"6c8a8d0a97d03b44e9528d30b30c70cb9d61b405","analyzedAt":"2026-08-15T06:53:27.215Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}