{"record":{"id":"f4d60a76cd906f59","repo":"fatedier/frp","slug":"range-number-is-invalid-f4d60a","errorCode":null,"errorMessage":"range number is invalid","messagePattern":"range number is invalid","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/util/util/util.go","lineNumber":99,"sourceCode":"\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\n\t\t\t}\n\t\t\tfor i := minValue; i <= maxValue; i++ {\n\t\t\t\tnumbers = append(numbers, i)\n\t\t\t}\n\t\tdefault:\n\t\t\terr = fmt.Errorf(\"range number is invalid\")\n\t\t\treturn\n\t\t}\n\t}\n\treturn\n}\n\nfunc GenerateResponseErrorString(summary string, err error, detailed bool) string {\n\tif detailed {\n\t\treturn err.Error()\n\t}\n\treturn summary","sourceCodeStart":81,"sourceCodeEnd":117,"githubUrl":"https://github.com/fatedier/frp/blob/6c8a8d0a97d03b44e9528d30b30c70cb9d61b405/pkg/util/util/util.go#L81-L117","documentation":"Returned by ParseRangeNumbers when a range token's bounds parse successfully but maxValue < minValue, e.g. \"2000-1000\". This variant carries no %v detail because it is a semantic (not syntactic) failure: the range is inverted. Expansion of an inverted range is rejected rather than silently producing an empty set.","triggerScenarios":"Any dash-separated token where the left number is greater than the right: \"9000-8000\". Config fields for port ranges in frpc/frps parsed by ParseRangeNumbers.","commonSituations":"Reordering ports while editing config and swapping the bounds; auto-generated range templates filled in the wrong order.","solutions":["Swap the bounds so the smaller number comes first: \"8000-9000\"","Prefer explicit single ports if you only need a few, avoiding long ranges","Verify with frpc verify before restarting the client"],"exampleFix":"# before\nports = \"9100-9000\"\n\n# after\nports = \"9000-9100\"","handlingStrategy":"validation","validationCode":"func rangeOrderValid(s string) bool {\n    for _, tok := range strings.Split(s, \",\") {\n        parts := strings.Split(strings.TrimSpace(tok), \"-\")\n        if len(parts) == 2 {\n            lo, e1 := strconv.ParseInt(strings.TrimSpace(parts[0]), 10, 64)\n            hi, e2 := strconv.ParseInt(strings.TrimSpace(parts[1]), 10, 64)\n            if e1 != nil || e2 != nil || hi < lo { return false }\n        }\n    }\n    return true\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Always write ranges low-high","Diff-review config edits that touch range values","frpc verify fails fast on inverted ranges"],"tags":["config","validation","ports","range"],"backgroundTag":null,"analyzedSha":"6c8a8d0a97d03b44e9528d30b30c70cb9d61b405","analyzedAt":"2026-08-15T06:53:27.215Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}