{"record":{"id":"0d96d75541e4d18f","repo":"apereo/cas","slug":"multiple-records-found-for-username","errorCode":null,"errorMessage":"Multiple records found for [username]","messagePattern":"Multiple records found for \\[username\\]","errorType":"exception","errorClass":"FailedLoginException","httpStatus":null,"severity":"error","filePath":"support/cas-server-support-jdbc-authentication/src/main/java/org/apereo/cas/jdbc/QueryAndEncodeDatabaseAuthenticationHandler.java","lineNumber":79,"sourceCode":"                val dbExpired = sqlQueryResults.get(properties.getExpiredFieldName()).toString();\n                if (BooleanUtils.toBoolean(dbExpired) || \"1\".equals(dbExpired)) {\n                    throw new AccountPasswordMustChangeException(\"Password has expired\");\n                }\n            }\n            if (StringUtils.isNotBlank(properties.getDisabledFieldName()) && sqlQueryResults.containsKey(properties.getDisabledFieldName())) {\n                val dbDisabled = sqlQueryResults.get(properties.getDisabledFieldName()).toString();\n                if (BooleanUtils.toBoolean(dbDisabled) || \"1\".equals(dbDisabled)) {\n                    throw new AccountDisabledException(\"Account has been disabled\");\n                }\n            }\n            val attributes = collectPrincipalAttributes(sqlQueryResults);\n            val principal = principalFactory.createPrincipal(username, attributes);\n            return createHandlerResult(transformedCredential, principal, new ArrayList<>());\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);\n        } catch (final DataAccessException e) {\n            throw new PreventedException(e);\n        }\n    }\n\n    protected Map<String, Object> performSqlQuery(final String username) {\n        return getJdbcTemplate().queryForMap(properties.getSql(), username);\n    }\n}\n","sourceCodeStart":61,"sourceCodeEnd":89,"githubUrl":"https://github.com/apereo/cas/blob/e7288fc434b4f4505b8452e1a57e8fb3111bb863/support/cas-server-support-jdbc-authentication/src/main/java/org/apereo/cas/jdbc/QueryAndEncodeDatabaseAuthenticationHandler.java#L61-L89","documentation":"When the SQL query returns more than one row, the resulting IncorrectResultSizeDataAccessException (actualSize > 0) is rethrown as FailedLoginException('Multiple records found for [username]'). The handler requires the query to return exactly one row per user and refuses to guess which record is correct.","triggerScenarios":"performSqlQuery(username) returns 2+ rows for the submitted username; e.g. duplicate rows in the users table or a non-unique join producing one row per matching relation.","commonSituations":"Duplicate user rows from a bad import or missing unique constraint, LEFT JOIN to a 1-N table (roles, mfa rows) inflating row count, case-insensitive duplicates ('John'/'john').","solutions":["Deduplicate the user rows in the database and add a unique constraint on the username column","Rewrite the SQL so it returns exactly one row (DISTINCT, LIMIT 1, or aggregate the joined rows)","Remove N:1 joins or move role/attribute collection to a separate attribute source","Normalize case-sensitive duplicate usernames"],"exampleFix":"// before\n// cas.authn.jdbc.encode[0].sql=SELECT * FROM users u JOIN user_roles r ON r.user_id=u.id WHERE u.username=?\n// after\n// cas.authn.jdbc.encode[0].sql=SELECT * FROM users WHERE username=?","handlingStrategy":"validation","validationCode":"List<Map<String,Object>> rows = jdbc.queryForList(sql, username);\nif (rows.size() != 1) throw new IllegalStateException(\"SQL must return exactly 1 row, got \" + rows.size() + \" for \" + username);","typeGuard":null,"tryCatchPattern":"try {\n    authResult = handler.authenticate(credential);\n} catch (FailedLoginException e) {\n    if (e.getMessage().startsWith(\"Multiple records\")) {\n        alertDataIntegrityTeam(username); // duplicates are a data problem, not a login problem\n    }\n    throw new BadCredentialsException(\"Invalid credentials\");\n}","preventionTips":["Add a UNIQUE constraint on the username column","Avoid 1:N joins in the auth sql or use DISTINCT/aggregation","Monitor for this message as a data-integrity signal","Validate the sql at deploy time returns one row for test users"],"tags":["jdbc","data-integrity","duplicate-rows"],"backgroundTag":"duplicate-user-record","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"}