fatedier/frp · error

VirtualNet feature is not enabled; enable it by setting the

Error message

VirtualNet feature is not enabled; enable it by setting the appropriate feature gate flag

What it means

frp's client config validator rejects a configuration that sets virtualNet.address but does not enable the VirtualNet feature gate. Feature gates are an opt-in mechanism for experimental features, so the virtual network configuration is only honored when the gate 'VirtualNet' is explicitly set. The check runs during ValidateClientCommonConfig before the client starts.

Source

Thrown at pkg/config/v1/validation/client.go:61

	}

	for _, validator := range validators {
		w, err := validator()
		warnings = AppendError(warnings, w)
		errs = AppendError(errs, err)
	}
	return warnings, errs
}

func validateFeatureGates(c *v1.ClientCommonConfig) (Warning, error) {
	gates := featuregate.NewFeatureGate()
	if err := gates.SetFromMap(c.FeatureGates); err != nil {
		return nil, err
	}

	if c.VirtualNet.Address != "" {
		if !gates.Enabled(featuregate.VirtualNet) {
			return nil, fmt.Errorf("VirtualNet feature is not enabled; enable it by setting the appropriate feature gate flag")
		}
	}
	return nil, nil
}

// ClientConfigRequirements describes runtime capabilities needed by a client configuration.
type ClientConfigRequirements struct {
	VirtualNet bool
}

// GetClientConfigRequirements returns the runtime capabilities needed by a client configuration.
func GetClientConfigRequirements(
	common *v1.ClientCommonConfig,
	proxyCfgs []v1.ProxyConfigurer,
	visitorCfgs []v1.VisitorConfigurer,
) ClientConfigRequirements {
	requirements := ClientConfigRequirements{}
	if common != nil && common.VirtualNet.Address != "" {

View on GitHub (pinned to 6c8a8d0a97)

Solutions

  1. Add featureGates = { VirtualNet = true } (TOML: [featureGates]\nVirtualNet = true) to the client config
  2. Verify the gate key casing matches featuregate.VirtualNet exactly (case-sensitive)
  3. If you do not need the virtual network, remove the [virtualNet] section (address field) from the config
  4. Check frp release notes: VirtualNet is experimental and may require a build/version that includes it

Example fix

# before
[featureGates]
# (missing)

[virtualNet]
address = "10.26.0.1/16"

# after
[featureGates]
VirtualNet = true

[virtualNet]
address = "10.26.0.1/16"
Defensive patterns

Strategy: validation

Validate before calling

// Before starting frpc, validate the pair in Go:
func hasVirtualNetGate(c *v1.ClientCommonConfig) bool {
    gates := featuregate.NewFeatureGate()
    if err := gates.SetFromMap(c.FeatureGates); err != nil {
        return false
    }
    return gates.Enabled(featuregate.VirtualNet) || c.VirtualNet.Address == ""
}

Try / catch

if _, err := validation.ValidateClientCommonConfig(cfg); err != nil {
    if strings.Contains(err.Error(), "VirtualNet feature is not enabled") {
        // set FeatureGates["VirtualNet"]=true or clear VirtualNet.Address, then retry validation
    }
    return err
}

Prevention

When it happens

Trigger: ClientCommonConfig has FeatureGates = nil or lacks key "VirtualNet", while c.VirtualNet.Address is non-empty. Happens when loading a TOML/YAML/JSON client config with a [virtualNet] section but no [featureGates] VirtualNet = true entry, or when gates.SetFromMap fails to see the key.

Common situations: Copying a virtualNet config block from docs or another machine without the featureGates block; upgrading frp where VirtualNet moved behind a gate; typos in the gate key (e.g. 'virtualnet' lowercase) so the gate map parses but never matches featuregate.VirtualNet.

Related errors


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