{"record":{"id":"d3394afbd786dc66","repo":"fatedier/frp","slug":"cannot-set-feature-gate-v-to-v-feature-is-locke","errorCode":null,"errorMessage":"cannot set feature gate %v to %v, feature is locked to %v","messagePattern":"cannot set feature gate (.+?) to (.+?), feature is locked to (.+?)","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/policy/featuregate/feature_gate.go","lineNumber":121,"sourceCode":"\n// SetFromMap sets feature gate values from a map[string]bool\nfunc (f *featureGate) SetFromMap(m map[string]bool) error {\n\tf.lock.Lock()\n\tdefer f.lock.Unlock()\n\n\t// Copy existing state\n\tknown := maps.Clone(f.known.Load().(map[Feature]FeatureSpec))\n\tenabled := maps.Clone(f.enabled.Load().(map[Feature]bool))\n\n\t// Apply the new settings\n\tfor k, v := range m {\n\t\tk := Feature(k)\n\t\tfeatureSpec, ok := known[k]\n\t\tif !ok {\n\t\t\treturn fmt.Errorf(\"unrecognized feature gate: %s\", k)\n\t\t}\n\t\tif featureSpec.LockToDefault && featureSpec.Default != v {\n\t\t\treturn fmt.Errorf(\"cannot set feature gate %v to %v, feature is locked to %v\", k, v, featureSpec.Default)\n\t\t}\n\t\tenabled[k] = v\n\t}\n\n\t// Persist the changes\n\tf.known.Store(known)\n\tf.enabled.Store(enabled)\n\treturn nil\n}\n\n// Add adds features to the feature gate\nfunc (f *featureGate) Add(features map[Feature]FeatureSpec) error {\n\tf.lock.Lock()\n\tdefer f.lock.Unlock()\n\n\tif f.closed {\n\t\treturn fmt.Errorf(\"cannot add feature gates after the feature gate is closed\")\n\t}","sourceCodeStart":103,"sourceCodeEnd":139,"githubUrl":"https://github.com/fatedier/frp/blob/6c8a8d0a97d03b44e9528d30b30c70cb9d61b405/pkg/policy/featuregate/feature_gate.go#L103-L139","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Remove that gate from your Set/config — it cannot be changed by design","Check the feature's FeatureSpec: the locked default is the only legal value","If you truly need the other value, use a frp build/version where the gate is not locked"],"exampleFix":"// before\nfg.Set(map[string]bool{\"LockedGate\": false}) // error: locked to true\n\n// after — omit locked gates entirely\nfg.Set(map[string]bool{\"UnlockedGate\": true})","handlingStrategy":"validation","validationCode":"// Skip locked gates before calling Set\nspecs, _ := fg.KnownFeatures()\nsettable := map[string]bool{}\nfor k, v := range requested {\n    if s, ok := specs[k]; ok && !s.LockToDefault {\n        settable[k] = v\n    }\n}\nreturn fg.Set(settable)","typeGuard":null,"tryCatchPattern":"if err := fg.Set(requested); err != nil && strings.Contains(err.Error(), \"locked to\") {\n    log.Warn(\"ignoring locked feature gate:\", err)\n}","preventionTips":["Never put locked (LockToDefault) gates in user config files","Drop stale gate entries from config when upgrading frp versions"],"tags":["feature-flags","configuration","go"],"backgroundTag":null,"analyzedSha":"6c8a8d0a97d03b44e9528d30b30c70cb9d61b405","analyzedAt":"2026-08-15T06:53:27.215Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}