fatedier/frp · error

VirtualNet-dependent configuration requires a VirtualNet run

Error message

VirtualNet-dependent configuration requires a VirtualNet runtime enabled at startup; restart frpc after configuring featureGates.VirtualNet and virtualNet.address

What it means

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.

Source

Thrown at client/service.go:516

	if aggregator == nil {
		return errors.New("config aggregator is not initialized")
	}

	svr.cfgMu.RLock()
	reloadCommon := svr.reloadCommon
	svr.cfgMu.RUnlock()

	proxies, visitors, err := aggregator.Load()
	if err != nil {
		return fmt.Errorf("reload config from sources failed: %w", err)
	}

	proxies, visitors = config.FilterClientConfigurers(reloadCommon, proxies, visitors)
	proxies = config.CompleteProxyConfigurers(proxies)
	visitors = config.CompleteVisitorConfigurers(visitors)
	requirements := validation.GetClientConfigRequirements(reloadCommon, proxies, visitors)
	if svr.vnetController == nil && requirements.VirtualNet {
		return errors.New(
			"VirtualNet-dependent configuration requires a VirtualNet runtime enabled at startup; " +
				"restart frpc after configuring featureGates.VirtualNet and virtualNet.address",
		)
	}

	// Atomically replace the entire configuration
	if err := svr.UpdateAllConfigurer(proxies, visitors); err != nil {
		return err
	}
	return nil
}

View on GitHub (pinned to 6c8a8d0a97)

Solutions

  1. Set featureGates.VirtualNet = true and virtualNet.address in frpc startup config, then restart frpc (the message says exactly this)
  2. Alternatively remove the VirtualNet-dependent proxy/visitor from config before reloading
  3. After restart, verify the vnet controller is active before reloading again
  4. Keep VirtualNet-dependent proxies out of configs for instances not started with the feature

Example fix

# before: frpc.toml has a virtual-net proxy but frpc started plain
# reload -> error

# after: add to frpc.toml and restart the process
featureGates:
  VirtualNet: true
virtualNet:
  address = "10.26.0.1/16"
Defensive patterns

Strategy: validation

Validate before calling

// Before applying a reload, ensure startup-time features are present
requirements := validation.GetClientConfigRequirements(common, proxies, visitors)
if requirements.VirtualNet && vnetController == nil {
    return errors.New("configure featureGates.VirtualNet + virtualNet.address and restart frpc first")
}

Try / catch

if err := svr.applyReload(newCfg); err != nil {
    if strings.Contains(err.Error(), "VirtualNet runtime") {
        // keep old config running; instruct operator to restart with vnet enabled
        return preserveCurrentConfig(err)
    }
    return err
}

Prevention

When it happens

Trigger: 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.

Common situations: 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.

Related errors


AI-assisted analysis of fatedier/frp@6c8a8d0a97 (2026-08-15). Data as JSON: /api/errors/97f2d9e8a65614d0. Report an issue: GitHub.