fatedier/frp · error

failed to parse proxy %s, err: %v

Error message

failed to parse proxy %s, err: %v

What it means

Legacy ini loader: for a non-range proxy section (role defaults to 'server' when the role key is absent), NewProxyConfFromIni validates and maps the section onto the typed proxy config. Any validation failure — unknown proxy type, invalid port values, missing required fields, bad transport/plugin options — is wrapped here with the section name.

Source

Thrown at pkg/config/legacy/client.go:273

		if name == ini.DefaultSection || name == "common" || strings.HasPrefix(name, "range:") {
			continue
		}

		_, shouldStart := startProxy[name]
		if !startAll && !shouldStart {
			continue
		}

		roleType := section.Key("role").String()
		if roleType == "" {
			roleType = "server"
		}

		switch roleType {
		case "server":
			newConf, newErr := NewProxyConfFromIni(prefix, name, section)
			if newErr != nil {
				return nil, nil, fmt.Errorf("failed to parse proxy %s, err: %v", name, newErr)
			}
			proxyConfs[prefix+name] = newConf
		case "visitor":
			newConf, newErr := NewVisitorConfFromIni(prefix, name, section)
			if newErr != nil {
				return nil, nil, fmt.Errorf("failed to parse visitor %s, err: %v", name, newErr)
			}
			visitorConfs[prefix+name] = newConf
		default:
			return nil, nil, fmt.Errorf("proxy %s role should be 'server' or 'visitor'", name)
		}
	}
	return proxyConfs, visitorConfs, nil
}

func renderRangeProxyTemplates(f *ini.File, section *ini.Section) error {
	// Validation
	localPortStr := section.Key("local_port").String()

View on GitHub (pinned to 6c8a8d0a97)

Solutions

  1. Check the inner error text — NewProxyConfFromIni names the failing field or value
  2. Confirm type is one of tcp/udp/xtcp/stcp/sudp/https/http/tcpmux and the section's keys apply to that type
  3. Fix numeric fields: ports must be integers 0-65535 (0 only where random is allowed)
  4. Migrate the file to TOML and run frpc verify (frpc verify -c frpc.toml) to catch these before runtime

Example fix

; before
[ssh]
type = tcp
local_port = 22
remote_port = 7ooo   ; letter 'o' instead of zero

; after
[ssh]
type = tcp
local_port = 22
remote_port = 7000
Defensive patterns

Strategy: validation

Validate before calling

validTypes := map[string]bool{"tcp":true,"udp":true,"xtcp":true,"stcp":true,"sudp":true,"http":true,"https":true,"tcpmux":true}
if !validTypes[section.Key("type").String()] {
    return fmt.Errorf("proxy %s: invalid type", section.Name())
}
if p, err := section.Key("local_port").Int(); err != nil || p < 0 || p > 65535 {
    return fmt.Errorf("proxy %s: bad local_port", section.Name())
}

Prevention

When it happens

Trigger: A [proxy] section with type = 'tcp' but a non-numeric or out-of-range local_port/remote_port; type not in {tcp,udp,xtcp,stcp,sudp,http,https,tcpmux}; plugin.* keys with invalid values; negative or >65535 ports.

Common situations: Hand-editing ini configs and introducing typos ('loca_port'), switching type without updating type-specific keys, using remote_port=0 with a type that requires it (e.g. stcp visitor semantics), leftover keys from a different proxy type.

Understand the failure class

Related errors


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