{"record":{"id":"6dbc1cf6e6f122cc","repo":"gravitational/teleport","slug":"cannot-disable-multi-factor-authentication","errorCode":null,"errorMessage":"cannot disable multi-factor authentication","messagePattern":"cannot disable multi-factor authentication","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"lib/modules/modules.go","lineNumber":341,"sourceCode":"\n// SetModules sets the modules interface\nfunc SetModules(m Modules) {\n\tmutex.Lock()\n\tdefer mutex.Unlock()\n\tmodules = m\n}\n\n// GetModules returns the modules interface. It only works in the auth service\n// process, so any code that may be executed in a different context needs to\n// obtain modules or derived options from an auth-specific caller or an RPC\n// call to the auth server.\nfunc GetModules() Modules {\n\tmutex.Lock()\n\tdefer mutex.Unlock()\n\treturn modules\n}\n\nvar ErrCannotDisableSecondFactor = errors.New(\"cannot disable multi-factor authentication\")\n\n// ValidateResource performs additional resource checks.\nfunc ValidateResource(res types.Resource) error {\n\t// todo(tross): DELETE WHEN ABLE TO [remove env var, leave insecure test mode]\n\tallowNoSecondFactor, _ := strconv.ParseBool(os.Getenv(teleport.EnvVarAllowNoSecondFactor))\n\tif GetModules().Features().Cloud ||\n\t\t(!allowNoSecondFactor && !IsInsecureTestMode()) {\n\t\tswitch r := res.(type) {\n\t\tcase types.AuthPreference:\n\t\t\tif !r.IsSecondFactorEnforced() {\n\t\t\t\treturn trace.Wrap(ErrCannotDisableSecondFactor)\n\t\t\t}\n\t\t}\n\t}\n\n\t// All checks below are Cloud-specific.\n\tif !GetModules().Features().Cloud {\n\t\treturn nil","sourceCodeStart":323,"sourceCodeEnd":359,"githubUrl":"https://github.com/gravitational/teleport/blob/1283425b60ec5f60d509ba4c791183d452923ff7/lib/modules/modules.go#L323-L359","documentation":"Sentinel returned by Modules.ValidateResource (license/edition checks) when a cluster's auth preference change would turn off second-factor authentication while the current license or module set still requires MFA; callers in auth init wrap it with upgrade instructions.","triggerScenarios":"Thrown at lib/modules/modules.go:341 when the library encounters an invalid state.","commonSituations":"See trigger scenarios.","solutions":["Keep at least one second_factor method (webauthn, otp, or on) in the cluster_auth_preference","Upgrade the license/edition if you need to manage MFA settings differently"],"exampleFix":null,"handlingStrategy":"validation","validationCode":null,"typeGuard":null,"tryCatchPattern":null,"preventionTips":[],"tags":[],"backgroundTag":null,"analyzedSha":"1283425b60ec5f60d509ba4c791183d452923ff7","analyzedAt":"2026-09-02T04:06:41.601Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}