{"record":{"id":"e63d1d8057d4da14","repo":"fatedier/frp","slug":"failed-to-render-template-for-proxy-s-v","errorCode":null,"errorMessage":"failed to render template for proxy %s: %v","messagePattern":"failed to render template for proxy (.+?): (.+?)","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/config/legacy/client.go","lineNumber":248,"sourceCode":"\t}\n\n\tstartAll := len(startProxy) == 0\n\n\t// Build template sections from range section And append to ini.File.\n\trangeSections := make([]*ini.Section, 0)\n\tfor _, section := range f.Sections() {\n\n\t\tif !strings.HasPrefix(section.Name(), \"range:\") {\n\t\t\tcontinue\n\t\t}\n\n\t\trangeSections = append(rangeSections, section)\n\t}\n\n\tfor _, section := range rangeSections {\n\t\terr = renderRangeProxyTemplates(f, section)\n\t\tif err != nil {\n\t\t\treturn nil, nil, fmt.Errorf(\"failed to render template for proxy %s: %v\", section.Name(), err)\n\t\t}\n\t}\n\n\tfor _, section := range f.Sections() {\n\t\tname := section.Name()\n\n\t\tif name == ini.DefaultSection || name == \"common\" || strings.HasPrefix(name, \"range:\") {\n\t\t\tcontinue\n\t\t}\n\n\t\t_, shouldStart := startProxy[name]\n\t\tif !startAll && !shouldStart {\n\t\t\tcontinue\n\t\t}\n\n\t\troleType := section.Key(\"role\").String()\n\t\tif roleType == \"\" {\n\t\t\troleType = \"server\"","sourceCodeStart":230,"sourceCodeEnd":266,"githubUrl":"https://github.com/fatedier/frp/blob/6c8a8d0a97d03b44e9528d30b30c70cb9d61b405/pkg/config/legacy/client.go#L230-L266","documentation":"While loading a legacy ini client config, every section named with the 'range:' prefix is expanded by renderRangeProxyTemplates into one concrete proxy section per port. This error wraps any failure of that expansion, including the port-validation errors from errors 155-157 or port-number parse failures from util.ParseRangeNumbers.","triggerScenarios":"A [range:xxx] section where local_port/remote_port is empty, non-numeric, uses a malformed range (e.g. '2000-1000-'), has mismatched counts ('local_port = 6000-6002' with 'remote_port = 7000-7001'), or where creating the derived section fails. The %s is the range section name, e.g. 'range:web'.","commonSituations":"Converting a single proxy to a range and forgetting one of the two port keys; typos like '600O' instead of '6000'; assuming ranges auto-pad counts; using commas inside a dash range.","solutions":["Read the inner error — it pinpoints empty ports, invalid numbers, or count mismatch","Set both local_port and remote_port in the [range:...] section using single values, comma lists, or a-b ranges","Make both sides expand to the same number of ports (equal counts of comma-separated items and ranges)","Validate numbers are decimal port values with no stray characters"],"exampleFix":"; before\n[range:web]\ntype = tcp\nlocal_port = 6000-6002\nremote_port = 7000-7001   ; count mismatch (3 vs 2)\n\n; after\n[range:web]\ntype = tcp\nlocal_port = 6000-6002\nremote_port = 7000-7002","handlingStrategy":"validation","validationCode":"for _, s := range file.Sections() {\n    if strings.HasPrefix(s.Name(), \"range:\") {\n        if s.Key(\"local_port\").String() == \"\" || s.Key(\"remote_port\").String() == \"\" {\n            return fmt.Errorf(\"%s: range section needs local_port and remote_port\", s.Name())\n        }\n    }\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Pre-validate range sections for both port keys and equal expansion counts","Use symmetric a-b ranges on both sides","Run frpc verify (or the loader) in CI to catch range errors before deploy"],"tags":["frp","config","ini","range-proxy","legacy"],"backgroundTag":null,"analyzedSha":"6c8a8d0a97d03b44e9528d30b30c70cb9d61b405","analyzedAt":"2026-08-15T06:53:27.215Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}