fatedier/frp · error

cannot set feature gate %v to %v, feature is locked to %v

Error message

cannot set feature gate %v to %v, feature is locked to %v

What it means

An attempt to change a feature gate away from its default value, but the gate's FeatureSpec has LockToDefault: true. Locked gates are stage-locked (alpha/beta gates that must not be toggled in production); SetValues refuses and reports the locked default.

Source

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

// 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()

	if f.closed {
		return fmt.Errorf("cannot add feature gates after the feature gate is closed")
	}

View on GitHub (pinned to 6c8a8d0a97)

Solutions

  1. Remove that gate from your Set/config — it cannot be changed by design
  2. Check the feature's FeatureSpec: the locked default is the only legal value
  3. If you truly need the other value, use a frp build/version where the gate is not locked

Example fix

// before
fg.Set(map[string]bool{"LockedGate": false}) // error: locked to true

// after — omit locked gates entirely
fg.Set(map[string]bool{"UnlockedGate": true})
Defensive patterns

Strategy: validation

Validate before calling

// Skip locked gates before calling Set
specs, _ := fg.KnownFeatures()
settable := map[string]bool{}
for k, v := range requested {
    if s, ok := specs[k]; ok && !s.LockToDefault {
        settable[k] = v
    }
}
return fg.Set(settable)

Try / catch

if err := fg.Set(requested); err != nil && strings.Contains(err.Error(), "locked to") {
    log.Warn("ignoring locked feature gate:", err)
}

Prevention

When it happens

Trigger: Calling Set with a value different from featureSpec.Default for a feature whose spec declares LockToDefault — e.g. trying to enable/disable a locked alpha gate from config.

Common situations: Trying to turn off a GA-locked gate or turn on a locked deprecated gate via the featureGates config key; config copied from docs/examples that toggle gates the current version locks.

Related errors


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