fatedier/frp · error

visitor name in URL must match name in body

Error message

visitor name in URL must match name in body

What it means

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.

Solutions

  1. Set the body "name" to the same value as the URL path name.
  2. To rename, delete the visitor and create a new one.
  3. Assert body.name == URL name in client code before issuing the PUT.

Example fix

// before
PUT /api/visitors/visitor-a
{"name": "visitor-b", "type": "stcp", ...}

// after
PUT /api/visitors/visitor-a
{"name": "visitor-a", "type": "stcp", ...}
Defensive patterns

Strategy: validation

Validate before calling

func checkVisitorNameMatch(pathName string, body map[string]any) error {
    name, _ := body["name"].(string)
    if pathName != "" && name != pathName { return fmt.Errorf("body name %q != URL name %q", name, pathName) }
    return nil
}

Prevention

When it happens

Trigger: PUT /api/visitors/old-v with body {"name":"new-v", ...}; any update where pathName is non-empty and differs from the body name.

Common situations: 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.

Related errors


AI-assisted analysis of fatedier/frp@6c8a8d0a97 (2026-08-15). Data as JSON: /api/errors/92b1821be90fba6d. Report an issue: GitHub.

Appendix: source

Thrown at client/http/model/visitor_definition.go:27

type VisitorDefinition struct {
	Name string `json:"name"`
	Type string `json:"type"`

	STCP *v1.STCPVisitorConfig `json:"stcp,omitempty"`
	SUDP *v1.SUDPVisitorConfig `json:"sudp,omitempty"`
	XTCP *v1.XTCPVisitorConfig `json:"xtcp,omitempty"`
}

func (p *VisitorDefinition) Validate(pathName string, isUpdate bool) error {
	if strings.TrimSpace(p.Name) == "" {
		return fmt.Errorf("visitor name is required")
	}
	if !IsVisitorType(p.Type) {
		return fmt.Errorf("invalid visitor type: %s", p.Type)
	}
	if isUpdate && pathName != "" && pathName != p.Name {
		return fmt.Errorf("visitor name in URL must match name in body")
	}

	_, blockType, blockCount := p.activeBlock()
	if blockCount != 1 {
		return fmt.Errorf("exactly one visitor type block is required")
	}
	if blockType != p.Type {
		return fmt.Errorf("visitor type block %q does not match type %q", blockType, p.Type)
	}
	return nil
}

func (p *VisitorDefinition) ToConfigurer() (v1.VisitorConfigurer, error) {
	block, _, _ := p.activeBlock()
	if block == nil {
		return nil, fmt.Errorf("exactly one visitor type block is required")
	}

View on GitHub (pinned to 6c8a8d0a97)