fatedier/frp · error

local ports number should be same with remote ports number

Error message

local ports number should be same with remote ports number

What it means

Range-proxy validation: after util.ParseRangeNumbers expands both sides (single numbers, comma lists, and a-b ranges), the number of local ports must equal the number of remote ports so each local port pairs with exactly one remote port. A count mismatch aborts expansion, later surfacing as 'failed to render template for proxy ...' (error 151).

Source

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

	// Validation
	localPortStr := section.Key("local_port").String()
	remotePortStr := section.Key("remote_port").String()
	if localPortStr == "" || remotePortStr == "" {
		return fmt.Errorf("local_port or remote_port is empty")
	}

	localPorts, err := util.ParseRangeNumbers(localPortStr)
	if err != nil {
		return err
	}

	remotePorts, err := util.ParseRangeNumbers(remotePortStr)
	if err != nil {
		return err
	}

	if len(localPorts) != len(remotePorts) {
		return fmt.Errorf("local ports number should be same with remote ports number")
	}

	if len(localPorts) == 0 {
		return fmt.Errorf("local_port and remote_port is necessary")
	}

	// Templates
	prefix := strings.TrimSpace(strings.TrimPrefix(section.Name(), "range:"))

	for i := range localPorts {
		tmpname := fmt.Sprintf("%s_%d", prefix, i)

		tmpsection, err := f.NewSection(tmpname)
		if err != nil {
			return err
		}

		copySection(section, tmpsection)

View on GitHub (pinned to 6c8a8d0a97)

Solutions

  1. Count the ports each side expands to and make them equal
  2. For an a-b range of N ports, give the other side N values too (e.g. matching a-b range)
  3. Prefer symmetric ranges (6000-6002 / 7000-7002) to avoid manual counting

Example fix

; before
[range:web]
type = tcp
local_port = 6000-6003   ; 4 ports
remote_port = 7000-7002   ; 3 ports

; after
[range:web]
type = tcp
local_port = 6000-6003
remote_port = 7000-7003
Defensive patterns

Strategy: validation

Validate before calling

lp, err := util.ParseRangeNumbers(localStr); if err != nil { return err }
rp, err := util.ParseRangeNumbers(remoteStr); if err != nil { return err }
if len(lp) != len(rp) {
    return fmt.Errorf("local expands to %d ports, remote to %d; must match", len(lp), len(rp))
}

Prevention

When it happens

Trigger: local_port = '6000-6002' (3 ports) with remote_port = '7000-7001' (2 ports); or local_port = '6000,6001,6002' with remote_port = '7000,7002'. The error fires before any sections are generated.

Common situations: Editing one side of a range pair and forgetting the other; assuming frp cycles or truncates the shorter list; mixing a range on one side with a single value on the other.

Related errors


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