fatedier/frp · error
proxy type block %q does not match type %q
Error message
proxy type block %q does not match type %q
What it means
Returned by ProxyDefinition.Validate when the definition contains exactly one type block, but the block's kind disagrees with the top-level "type" string — e.g. type "tcp" with an "http" block. The block and the type field must denote the same proxy kind.
Source
Thrown at client/http/model/proxy_definition.go:40
}
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")
}
cfg := block
cfg.GetBaseConfig().Name = p.Name
cfg.GetBaseConfig().Type = p.Type
return cfg, nil
}
func ProxyDefinitionFromConfigurer(cfg v1.ProxyConfigurer) (ProxyDefinition, error) {
if cfg == nil {View on GitHub (pinned to 6c8a8d0a97)
Solutions
- Make "type" match the block key: type tcp goes with the "tcp" block, type http with the "http" block, etc.
- Keep type lowercase when correcting it.
- Derive "type" from the block you set, ideally in one place in the generating code.
Example fix
// before
{"name": "web", "type": "tcp", "http": {"localPort": 80}}
// after
{"name": "web", "type": "http", "http": {"localPort": 80, "customDomains": ["example.com"]}} Defensive patterns
Strategy: validation
Validate before calling
func blockMatchesType(def map[string]any) bool {
for _, k := range []string{"tcp","udp","http","https","tcpmux","stcp","sudp","xtcp"} {
if def[k] != nil { return def["type"] == k }
}
return false
} Prevention
- Set type and block together: type := blockKey at definition-build time.
- Never hand-edit one of the two fields independently.
- Lint generated configs for type/block agreement.
When it happens
Trigger: {"name":"x","type":"tcp","http":{"localPort":80}} — the http block is set but type says tcp. Also from case errors in "type" (e.g. "Http") that survive IsProxyType in some forks, or hand-edited JSON where one field was updated and the other was not.
Common situations: Changing the "type" field without swapping the block (or vice versa); generated configs where type and block come from different sources; copy-paste between definitions.
Related errors
- invalid proxy type: %s
- exactly one proxy type block is required
- proxy name is required
- proxy name in URL must match name in body
- visitor name is required
AI-assisted analysis of fatedier/frp@6c8a8d0a97 (2026-08-15).
Data as JSON: /api/errors/e8fd88a37752face.
Report an issue: GitHub.