{"record":{"id":"637d693cf8029368","repo":"apereo/cas","slug":"account-has-been-disabled-637d69","errorCode":null,"errorMessage":"Account has been disabled","messagePattern":"Account has been disabled","errorType":"exception","errorClass":"AccountDisabledException","httpStatus":null,"severity":"warning","filePath":"support/cas-server-support-jdbc-authentication/src/main/java/org/apereo/cas/jdbc/QueryDatabaseAuthenticationHandler.java","lineNumber":86,"sourceCode":"                    throw new FailedLoginException(\"Missing field 'total' from the query results for \" + username);\n                }\n\n                val count = dbFields.get(\"total\");\n                if (count == null || !NumberUtils.isCreatable(count.toString())) {\n                    throw new FailedLoginException(\"Missing field value 'total' from the query results for \"\n                        + username + \" or value not parseable as a number\");\n                }\n\n                val number = NumberUtils.createNumber(count.toString());\n                if (number.longValue() != 1) {\n                    throw new FailedLoginException(\"No records found for user \" + username);\n                }\n            }\n\n            if (StringUtils.isNotBlank(properties.getFieldDisabled()) && dbFields.containsKey(properties.getFieldDisabled())) {\n                val dbDisabled = dbFields.get(properties.getFieldDisabled()).toString();\n                if (BooleanUtils.toBoolean(dbDisabled) || \"1\".equals(dbDisabled)) {\n                    throw new AccountDisabledException(\"Account has been disabled\");\n                }\n            }\n            if (StringUtils.isNotBlank(properties.getFieldExpired()) && dbFields.containsKey(properties.getFieldExpired())) {\n                val dbExpired = dbFields.get(properties.getFieldExpired()).toString();\n                if (BooleanUtils.toBoolean(dbExpired) || \"1\".equals(dbExpired)) {\n                    throw new AccountPasswordMustChangeException(\"Password has expired\");\n                }\n            }\n\n            val attributes = collectPrincipalAttributes(dbFields);\n            val principal = this.principalFactory.createPrincipal(username, attributes);\n            return createHandlerResult(credential, principal, new ArrayList<>());\n\n        } catch (final IncorrectResultSizeDataAccessException e) {\n            if (e.getActualSize() == 0) {\n                throw new AccountNotFoundException(username + \" not found with SQL query\");\n            }\n            throw new FailedLoginException(\"Multiple records found for \" + username);","sourceCodeStart":68,"sourceCodeEnd":104,"githubUrl":"https://github.com/apereo/cas/blob/e7288fc434b4f4505b8452e1a57e8fb3111bb863/support/cas-server-support-jdbc-authentication/src/main/java/org/apereo/cas/jdbc/QueryDatabaseAuthenticationHandler.java#L68-L104","documentation":"QueryDatabaseAuthenticationHandler throws AccountDisabledException('Account has been disabled') when the row's column named by properties.getFieldDisabled() is truthy (BooleanUtils.toBoolean true or '1'). The credential check already passed; the account record is flagged disabled.","triggerScenarios":"dbFields contains the disabled-field column configured via cas.authn.jdbc.query[0].fieldDisabled and its value parses as a truthy boolean or the string \"1\".","commonSituations":"Admin-deactivated accounts, identity/HR sync flagging users, fieldDisabled accidentally mapped to a boolean-ish column that is 1 for all rows (e.g. 'locked' or a type flag).","solutions":["Re-enable the account in the database (set the flag to 0/false)","Verify fieldDisabled maps to the intended status column","Trace the provisioning job that set the flag if disabling was unexpected","Update the flag in the system of record so the next sync does not re-disable"],"exampleFix":"// before: fieldDisabled bound to always-1 column\n// cas.authn.jdbc.query[0].fieldDisabled=user_type\n// after\n// cas.authn.jdbc.query[0].fieldDisabled=account_disabled","handlingStrategy":"try-catch","validationCode":"Map<String,Object> row = jdbc.queryForMap(sql, user);\nObject flag = row.get(\"account_disabled\");\nboolean disabled = flag != null && (\"1\".equals(flag.toString()) || BooleanUtils.toBoolean(flag.toString()));\nif (disabled) return showAccountDisabledPage(user);","typeGuard":"boolean isTruthyFlag(Object v) { return v != null && (\"1\".equals(v.toString()) || BooleanUtils.toBoolean(v.toString())); }","tryCatchPattern":"try {\n    authResult = handler.authenticate(credential);\n} catch (AccountDisabledException e) {\n    // credentials valid; account administratively disabled\n    return showAccountDisabledNotice(user);\n}","preventionTips":["Point fieldDisabled at the actual account-status column, never a co-located boolean","Keep enable/disable state managed in a single system of record","Audit sync jobs that flip the disabled flag","Differentiate disabled-vs-expired-vs-wrong-password messages in your flow"],"tags":["jdbc","account-status","account-disabled"],"backgroundTag":"account-disabled","analyzedSha":"e7288fc434b4f4505b8452e1a57e8fb3111bb863","analyzedAt":"2026-09-08T15:39:16.015Z","contentChangedAt":"2026-09-08T15:39:16.015Z","schemaVersion":2},"datasetVersion":"2026-09-15T23:17:13.987Z"}