{"record":{"id":"222f24639cf6fd73","repo":"fatedier/frp","slug":"range-number-is-invalid-v-222f24","errorCode":null,"errorMessage":"range number is invalid, %v","messagePattern":"range number is invalid, (.+?)","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/util/util/util.go","lineNumber":82,"sourceCode":"\treturn\n}\n\nfunc ParseRangeNumbers(rangeStr string) (numbers []int64, err error) {\n\trangeStr = strings.TrimSpace(rangeStr)\n\tnumbers = make([]int64, 0)\n\t// e.g. 1000-2000,2001,2002,3000-4000\n\tnumRanges := strings.SplitSeq(rangeStr, \",\")\n\tfor numRangeStr := range numRanges {\n\t\t// 1000-2000 or 2001\n\t\tnumArray := strings.Split(numRangeStr, \"-\")\n\t\t// length: only 1 or 2 is correct\n\t\trangeType := len(numArray)\n\t\tswitch rangeType {\n\t\tcase 1:\n\t\t\t// single number\n\t\t\tsingleNum, errRet := strconv.ParseInt(strings.TrimSpace(numArray[0]), 10, 64)\n\t\t\tif errRet != nil {\n\t\t\t\terr = fmt.Errorf(\"range number is invalid, %v\", errRet)\n\t\t\t\treturn\n\t\t\t}\n\t\t\tnumbers = append(numbers, singleNum)\n\t\tcase 2:\n\t\t\t// range numbers\n\t\t\tminValue, errRet := strconv.ParseInt(strings.TrimSpace(numArray[0]), 10, 64)\n\t\t\tif errRet != nil {\n\t\t\t\terr = fmt.Errorf(\"range number is invalid, %v\", errRet)\n\t\t\t\treturn\n\t\t\t}\n\t\t\tmaxValue, errRet := strconv.ParseInt(strings.TrimSpace(numArray[1]), 10, 64)\n\t\t\tif errRet != nil {\n\t\t\t\terr = fmt.Errorf(\"range number is invalid, %v\", errRet)\n\t\t\t\treturn\n\t\t\t}\n\t\t\tif maxValue < minValue {\n\t\t\t\terr = fmt.Errorf(\"range number is invalid\")\n\t\t\t\treturn","sourceCodeStart":64,"sourceCodeEnd":100,"githubUrl":"https://github.com/fatedier/frp/blob/6c8a8d0a97d03b44e9528d30b30c70cb9d61b405/pkg/util/util/util.go#L64-L100","documentation":"Thrown by frp's ParseRangeNumbers when a single-number element of a port/range string cannot be parsed as an int64. The function accepts comma-separated specs like \"1000-2000,2001\"; for a bare token (no '-' present) it runs strconv.ParseInt, and this site wraps that failure. The %v in the message carries the underlying strconv error, which names the offending token.","triggerScenarios":"Passing a ports/remotePort range string where a comma-separated element with no dash is not a valid integer: \"2001abc\", \"\", \" 7 0x10\"; also values exceeding int64 or containing a sign/format ParseInt rejects in base 10. Called for config fields like ports in frpc proxy configs.","commonSituations":"Typo in frpc.toml such as ports = \"9000,900l\" or a trailing comma creating an empty token; copy-pasting a range with unicode dash or spaces around numbers; feeding port numbers in hex or with units (\"90k\").","solutions":["Correct the string to pure comma-separated numbers/ranges: ports = \"9000,9001,10000-10010\"","Remove trailing/leading commas and stray spaces (only TrimSpace around a token is allowed, not inside it)","Check the %v detail in the message: strconv error shows exactly which token failed","Validate config with `frpc verify` (or frpc verify -c ...) before deploying"],"exampleFix":"# before\nports = \"9000,900l,10000-10010\"\n\n# after\nports = \"9000,9001,10000-10010\"","handlingStrategy":"validation","validationCode":"var portRangeRe = regexp.MustCompile(`^\\s*\\d{1,19}\\s*(?:-\\s*\\d{1,19}\\s*)?(?:\\s*,\\s*\\d{1,19}\\s*(?:-\\s*\\d{1,19}\\s*)?)*$`)\n\nfunc validPortRange(s string) bool { return portRangeRe.MatchString(s) }","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Validate ports strings in CI with a lint step before deploying frpc","Generate port configs programmatically instead of hand-editing","Run `frpc verify -c frpc.toml` after every config change"],"tags":["config","validation","ports","parsing"],"backgroundTag":null,"analyzedSha":"6c8a8d0a97d03b44e9528d30b30c70cb9d61b405","analyzedAt":"2026-08-15T06:53:27.215Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}