fatedier/frp · error

local_port or remote_port is empty

Error message

local_port or remote_port is empty

What it means

First validation inside renderRangeProxyTemplates for [range:...] sections: the string values of local_port and remote_port must both be non-empty before range expansion. An empty (or absent) key aborts with this error, which then surfaces wrapped as 'failed to render template for proxy range:...' (error 151).

Source

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

		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()
	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")

View on GitHub (pinned to 6c8a8d0a97)

Solutions

  1. Add both local_port and remote_port keys with valid values or ranges to the [range:...] section
  2. Use the exact underscore-separated key names
  3. Remember ranges are mandatory in range sections even if a single proxy of the same type could omit them

Example fix

; before
[range:ssh]
type = tcp
local_port = 6000,6001
; remote_port missing

; after
[range:ssh]
type = tcp
local_port = 6000,6001
remote_port = 7000,7001
Defensive patterns

Strategy: validation

Validate before calling

if strings.TrimSpace(section.Key("local_port").String()) == "" ||
   strings.TrimSpace(section.Key("remote_port").String()) == "" {
    return fmt.Errorf("%s: local_port and remote_port are required in range sections", section.Name())
}

Prevention

When it happens

Trigger: A [range:...] section that defines only local_port, only remote_port, or neither; a key commented out or mistyped (e.g. localport without the underscore) so it reads as empty.

Common situations: Creating a range section by copying a normal proxy section that had a default remote_port behavior; typos in key names; commenting out one port while testing.

Related errors


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