{"record":{"id":"97f2d9e8a65614d0","repo":"fatedier/frp","slug":"virtualnet-dependent-configuration-requires-a-virt","errorCode":null,"errorMessage":"VirtualNet-dependent configuration requires a VirtualNet runtime enabled at startup; restart frpc after configuring featureGates.VirtualNet and virtualNet.address","messagePattern":"VirtualNet-dependent configuration requires a VirtualNet runtime enabled at startup; restart frpc after configuring featureGates\\.VirtualNet and virtualNet\\.address","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"client/service.go","lineNumber":516,"sourceCode":"\tif aggregator == nil {\n\t\treturn errors.New(\"config aggregator is not initialized\")\n\t}\n\n\tsvr.cfgMu.RLock()\n\treloadCommon := svr.reloadCommon\n\tsvr.cfgMu.RUnlock()\n\n\tproxies, visitors, err := aggregator.Load()\n\tif err != nil {\n\t\treturn fmt.Errorf(\"reload config from sources failed: %w\", err)\n\t}\n\n\tproxies, visitors = config.FilterClientConfigurers(reloadCommon, proxies, visitors)\n\tproxies = config.CompleteProxyConfigurers(proxies)\n\tvisitors = config.CompleteVisitorConfigurers(visitors)\n\trequirements := validation.GetClientConfigRequirements(reloadCommon, proxies, visitors)\n\tif svr.vnetController == nil && requirements.VirtualNet {\n\t\treturn errors.New(\n\t\t\t\"VirtualNet-dependent configuration requires a VirtualNet runtime enabled at startup; \" +\n\t\t\t\t\"restart frpc after configuring featureGates.VirtualNet and virtualNet.address\",\n\t\t)\n\t}\n\n\t// Atomically replace the entire configuration\n\tif err := svr.UpdateAllConfigurer(proxies, visitors); err != nil {\n\t\treturn err\n\t}\n\treturn nil\n}\n","sourceCodeStart":498,"sourceCodeEnd":528,"githubUrl":"https://github.com/fatedier/frp/blob/6c8a8d0a97d03b44e9528d30b30c70cb9d61b405/client/service.go#L498-L528","documentation":"During frpc hot reload (service.go:516), after loading and completing proxies/visitors the service computes requirements via validation.GetClientConfigRequirements; if any loaded item needs the VirtualNet runtime but frpc was started without one (vnetController == nil), reload is aborted with this error. VirtualNet state is established only at process start, so it cannot be brought up by a reload.","triggerScenarios":"Adding proxies/visitors that depend on virtual net (e.g. a proxy configured with a virtual net IP / vnet-required type) to the config sources, then triggering admin API reload while frpc was launched without featureGates.VirtualNet enabled and virtualNet.address set.","commonSituations":"Enabling a VirtualNet-dependent feature via config reload during testing; enabling the feature gate on frps but forgetting frpc startup flags; documented flow not followed because the operator assumed reload could activate networking features.","solutions":["Set featureGates.VirtualNet = true and virtualNet.address in frpc startup config, then restart frpc (the message says exactly this)","Alternatively remove the VirtualNet-dependent proxy/visitor from config before reloading","After restart, verify the vnet controller is active before reloading again","Keep VirtualNet-dependent proxies out of configs for instances not started with the feature"],"exampleFix":"# before: frpc.toml has a virtual-net proxy but frpc started plain\n# reload -> error\n\n# after: add to frpc.toml and restart the process\nfeatureGates:\n  VirtualNet: true\nvirtualNet:\n  address = \"10.26.0.1/16\"","handlingStrategy":"validation","validationCode":"// Before applying a reload, ensure startup-time features are present\nrequirements := validation.GetClientConfigRequirements(common, proxies, visitors)\nif requirements.VirtualNet && vnetController == nil {\n    return errors.New(\"configure featureGates.VirtualNet + virtualNet.address and restart frpc first\")\n}","typeGuard":null,"tryCatchPattern":"if err := svr.applyReload(newCfg); err != nil {\n    if strings.Contains(err.Error(), \"VirtualNet runtime\") {\n        // keep old config running; instruct operator to restart with vnet enabled\n        return preserveCurrentConfig(err)\n    }\n    return err\n}","preventionTips":["Document that VirtualNet is startup-only; reload cannot enable it","Validate requirements before swapping configs so a failed reload never halves state","Automate the restart flow when vnet-dependent proxies are first introduced"],"tags":["go","frpc","virtual-net","reload","feature-gates"],"backgroundTag":null,"analyzedSha":"6c8a8d0a97d03b44e9528d30b30c70cb9d61b405","analyzedAt":"2026-08-15T06:53:27.215Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}