{"record":{"id":"70447390f81c9ff0","repo":"fatedier/frp","slug":"first-and-second-range-numbers-are-not-in-pairs","errorCode":null,"errorMessage":"first and second range numbers are not in pairs","messagePattern":"first and second range numbers are not in pairs","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/config/template.go","lineNumber":38,"sourceCode":"\t\"github.com/fatedier/frp/pkg/util/util\"\n)\n\ntype NumberPair struct {\n\tFirst  int64\n\tSecond int64\n}\n\nfunc parseNumberRangePair(firstRangeStr, secondRangeStr string) ([]NumberPair, error) {\n\tfirstRangeNumbers, err := util.ParseRangeNumbers(firstRangeStr)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\tsecondRangeNumbers, err := util.ParseRangeNumbers(secondRangeStr)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\tif len(firstRangeNumbers) != len(secondRangeNumbers) {\n\t\treturn nil, fmt.Errorf(\"first and second range numbers are not in pairs\")\n\t}\n\tpairs := make([]NumberPair, 0, len(firstRangeNumbers))\n\tfor i := range firstRangeNumbers {\n\t\tpairs = append(pairs, NumberPair{\n\t\t\tFirst:  firstRangeNumbers[i],\n\t\t\tSecond: secondRangeNumbers[i],\n\t\t})\n\t}\n\treturn pairs, nil\n}\n\nfunc parseNumberRange(firstRangeStr string) ([]int64, error) {\n\treturn util.ParseRangeNumbers(firstRangeStr)\n}\n","sourceCodeStart":20,"sourceCodeEnd":53,"githubUrl":"https://github.com/fatedier/frp/blob/6c8a8d0a97d03b44e9528d30b30c70cb9d61b405/pkg/config/template.go#L20-L53","documentation":"Thrown by parseNumberRangePair in pkg/config/template.go when building a proxy's port-pair mapping (e.g. TCP port multiplexing / per-port plugin configs that pair two port ranges). Both range strings are expanded into concrete number lists via util.ParseRangeNumbers, and the two lists must contain exactly the same count so element i of the first range maps to element i of the second. If the counts differ, no 1:1 pairing exists and the function aborts with this error. It surfaces during TOML/INI/JSON config conversion into the v1 format, before the client connects.","triggerScenarios":"A proxy config declares two ranges that expand to different lengths, e.g. first range \"2000-2003\" (4 numbers) paired with second range \"6000-6001\" (2 numbers), or a single value \"8080\" paired with a range \"9000-9002\". Any parseNumberRangePair call where len(ParseRangeNumbers(a)) != len(ParseRangeNumbers(b)).","commonSituations":"Converting an old frp INI/TOML config (with paired port-range settings such as plugin port mappings) where one side of the pair was edited and the other was not; copy-paste of range examples from docs where the sample ranges have different spans; assuming a single value can pair with a multi-value range.","solutions":["Make both ranges expand to the same number of ports, e.g. \"2000-2003\" with \"6000-6003\" (4 ports each), or pair single values \"2000\" with \"6000\".","Count both sides explicitly: N numbers on the first side requires exactly N numbers on the second side (a range a-b expands to b-a+1 numbers).","If you intended one value to map to many, restructure the config as multiple proxy entries or use a range on both sides of equal length."],"exampleFix":"# before\nrange1 = \"2000-2003\"\nrange2 = \"6000-6001\"\n\n# after\nrange1 = \"2000-2003\"\nrange2 = \"6000-6003\"","handlingStrategy":"validation","validationCode":"// Expand both ranges and require equal lengths before calling parseNumberRangePair.\nfunc rangesPairable(a, b string) error {\n\tna, err := util.ParseRangeNumbers(a)\n\tif err != nil {\n\t\treturn fmt.Errorf(\"first range invalid: %w\", err)\n\t}\n\tnb, err := util.ParseRangeNumbers(b)\n\tif err != nil {\n\t\treturn fmt.Errorf(\"second range invalid: %w\", err)\n\t}\n\tif len(na) != len(nb) {\n\t\treturn fmt.Errorf(\"range %q has %d numbers but %q has %d; counts must match\", a, len(na), b, len(nb))\n\t}\n\treturn nil\n}","typeGuard":"func isPairableRange(a, b string) bool {\n\tna, err1 := util.ParseRangeNumbers(a)\n\tnb, err2 := util.ParseRangeNumbers(b)\n\treturn err1 == nil && err2 == nil && len(na) == len(nb)\n}","tryCatchPattern":null,"preventionTips":["Remember a range a-b expands to b-a+1 numbers; count both sides before pairing.","Never pair a single value with a multi-value range.","Add a config lint step that checks paired ranges expand to equal lengths."],"tags":["go","frp","config","port-range","validation"],"backgroundTag":null,"analyzedSha":"6c8a8d0a97d03b44e9528d30b30c70cb9d61b405","analyzedAt":"2026-08-15T06:53:27.215Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}