fatedier/frp · error
range number is invalid, %v
Error message
range number is invalid, %v
What it means
Thrown while unmarshalling a PortsRange value (pkg/config/types/types.go) when a comma-separated port list contains a single token that is not a valid 64-bit integer. The parser splits the string on commas, then on '-'; a token with no dash is treated as a single port and must parse with strconv.ParseInt. Any syntax or overflow failure (wrapped with %v) produces this error during PortsRange.UnmarshalJSON.
Source
Thrown at pkg/config/types/types.go:151
return strings.Join(strs, ",")
}
// the format of str is like "1000-2000,3000,4000-5000"
func NewPortsRangeSliceFromString(str string) ([]PortsRange, error) {
str = strings.TrimSpace(str)
out := []PortsRange{}
numRanges := strings.SplitSeq(str, ",")
for numRangeStr := range numRanges {
// 1000-2000 or 2001
numArray := strings.Split(numRangeStr, "-")
// length: only 1 or 2 is correct
rangeType := len(numArray)
switch rangeType {
case 1:
// single number
singleNum, err := strconv.ParseInt(strings.TrimSpace(numArray[0]), 10, 64)
if err != nil {
return nil, fmt.Errorf("range number is invalid, %v", err)
}
out = append(out, PortsRange{Single: int(singleNum)})
case 2:
// range numbers
minNum, err := strconv.ParseInt(strings.TrimSpace(numArray[0]), 10, 64)
if err != nil {
return nil, fmt.Errorf("range number is invalid, %v", err)
}
maxNum, err := strconv.ParseInt(strings.TrimSpace(numArray[1]), 10, 64)
if err != nil {
return nil, fmt.Errorf("range number is invalid, %v", err)
}
if maxNum < minNum {
return nil, fmt.Errorf("range number is invalid")
}
out = append(out, PortsRange{Start: int(minNum), End: int(maxNum)})
default:
return nil, fmt.Errorf("range number is invalid")View on GitHub (pinned to 6c8a8d0a97)
Solutions
- Correct the offending token to a plain decimal integer within int64 range (and practical port range 0-65535), e.g. "8080".
- Remove trailing/leading commas and stray whitespace in the comma-separated port list.
- Replace service names with their numeric port equivalents (http -> 80, ssh -> 22).
Example fix
# before remotePort = "80 80" # after remotePort = 8080
Defensive patterns
Strategy: validation
Validate before calling
// Validate every comma-separated token is a plain int64 before unmarshalling.
func validPortsString(s string) error {
for _, tok := range strings.Split(s, ",") {
if _, err := strconv.ParseInt(strings.TrimSpace(tok), 10, 64); err != nil {
return fmt.Errorf("bad port token %q: %w", tok, err)
}
}
return nil
} Type guard
func isPlainPort(s string) bool {
_, err := strconv.ParseInt(strings.TrimSpace(s), 10, 64)
return err == nil
} Prevention
- Use plain decimal integers only; no hex, names, or separators.
- Run frpc verify (or your loader) in CI to catch port string typos before deploy.
- Watch for trailing commas and stray spaces in port lists.
When it happens
Trigger: PortsRange JSON unmarshal on input like "808 0" (space), "0x50" (hex not supported), "http" (non-numeric), "99999999999999999999" (int64 overflow), or a trailing comma producing an empty token.
Common situations: Typos in remotePort/localPort strings in frpc TOML/JSON; pasting IANA service names ("http", "ssh") where frp expects numeric ports; a trailing comma in a JSON port list; values copied from a spreadsheet with non-breaking spaces or thousand separators.
Related errors
- range number is invalid
- first and second range numbers are not in pairs
- unknown proxy type: %s
- unmarshal ProxyConfig error: %v
- unmarshal proxy plugin error: %v
AI-assisted analysis of fatedier/frp@6c8a8d0a97 (2026-08-15).
Data as JSON: /api/errors/4d3de3210e2d4010.
Report an issue: GitHub.