fatedier/frp · error

proxy name in URL must match name in body

Error message

proxy name in URL must match name in body

What it means

Returned by ProxyDefinition.Validate during an update (PUT /api/proxies/{name}) when the name in the URL path differs from the "name" field in the JSON body. frpc refuses to rename a proxy via update because the name is its identity key; both must agree.

Source

Thrown at client/http/model/proxy_definition.go:32

	TCP    *v1.TCPProxyConfig    `json:"tcp,omitempty"`
	UDP    *v1.UDPProxyConfig    `json:"udp,omitempty"`
	HTTP   *v1.HTTPProxyConfig   `json:"http,omitempty"`
	HTTPS  *v1.HTTPSProxyConfig  `json:"https,omitempty"`
	TCPMux *v1.TCPMuxProxyConfig `json:"tcpmux,omitempty"`
	STCP   *v1.STCPProxyConfig   `json:"stcp,omitempty"`
	SUDP   *v1.SUDPProxyConfig   `json:"sudp,omitempty"`
	XTCP   *v1.XTCPProxyConfig   `json:"xtcp,omitempty"`
}

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

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

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

View on GitHub (pinned to 6c8a8d0a97)

Solutions

  1. Make the body's "name" identical to the name in the URL path.
  2. To rename a proxy, DELETE the old one and POST a new definition — updates cannot change identity.
  3. Add an assertion in client code that body.name == URL name before sending the PUT.

Example fix

// before
PUT /api/proxies/ssh-old
{"name": "ssh-new", "type": "tcp", ...}

// after
PUT /api/proxies/ssh-old
{"name": "ssh-old", "type": "tcp", ...}
Defensive patterns

Strategy: validation

Validate before calling

func checkNameMatch(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/proxies/old-name with body {"name": "new-name", ...}; also triggers when pathName is provided and body name is a different non-empty string. It only applies when isUpdate is true (updates), not creates.

Common situations: Client code templating the body with a new name while keeping the old URL; attempting to rename a proxy with PUT instead of delete+create; stale cached body from a previous proxy being reused for a different one.

Related errors


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