fatedier/frp · error

unrecognized feature gate: %s

Error message

unrecognized feature gate: %s

What it means

featureGate.SetValues (via Set) was given a feature name that was never registered with Add. The gate keeps a known-features map; setting any key outside it fails atomically before state is persisted. This mirrors Kubernetes feature-gate semantics and protects against silently ignoring typos.

Source

Thrown at pkg/policy/featuregate/feature_gate.go:118

	f.enabled.Store(map[Feature]bool{})
	return f
}

// SetFromMap sets feature gate values from a map[string]bool
func (f *featureGate) SetFromMap(m map[string]bool) error {
	f.lock.Lock()
	defer f.lock.Unlock()

	// Copy existing state
	known := maps.Clone(f.known.Load().(map[Feature]FeatureSpec))
	enabled := maps.Clone(f.enabled.Load().(map[Feature]bool))

	// Apply the new settings
	for k, v := range m {
		k := Feature(k)
		featureSpec, ok := known[k]
		if !ok {
			return fmt.Errorf("unrecognized feature gate: %s", k)
		}
		if featureSpec.LockToDefault && featureSpec.Default != v {
			return fmt.Errorf("cannot set feature gate %v to %v, feature is locked to %v", k, v, featureSpec.Default)
		}
		enabled[k] = v
	}

	// Persist the changes
	f.known.Store(known)
	f.enabled.Store(enabled)
	return nil
}

// Add adds features to the feature gate
func (f *featureGate) Add(features map[Feature]FeatureSpec) error {
	f.lock.Lock()
	defer f.lock.Unlock()

View on GitHub (pinned to 6c8a8d0a97)

Solutions

  1. List valid gates via the gate's String()/known map to find the exact accepted names
  2. Correct the typo or drop the removed gate from your configuration
  3. If the gate should exist, ensure Add() ran before SetValues (initialization order)

Example fix

// before
fg.Set(map[string]bool{
  "SupportXTCPCQuic": true, // never registered
})

// after (use a gate actually registered by Add)
fg.Set(map[string]bool{
  "SomeRegisteredGate": true,
})
Defensive patterns

Strategy: validation

Validate before calling

// Check gate existence before setting
all, _ := fg.KnownFeatures() // or export the known map
for k := range requested {
    if _, ok := all[k]; !ok {
        return fmt.Errorf("unknown feature gate %q; available: %v", k, all)
    }
}
return fg.Set(requested)

Try / catch

if err := fg.Set(requested); err != nil && strings.Contains(err.Error(), "unrecognized feature gate") {
    // fail fast on typos; do not silently ignore
    return err
}

Prevention

When it happens

Trigger: Calling Set(map[string]bool{"SomeFeature": true}) where "SomeFeature" is not in f.known — typo, feature removed in this version, or gate not yet populated via Add.

Common situations: Carrying old feature-flag config into a frp version that renamed/removed a gate; typo in the featureGates config string; setting a gate before the owning package registered it.

Related errors


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