spring-projects/spring-security · error · IncorrectResultSizeDataAccessException
[N] users found with name 'X', expected 1
Error message
[N] users found with name 'X', expected 1
What it means
JdbcUserDetailsManager.userExists expects exactly zero or one row for the username; if the count query returns null or more than 1, it throws IncorrectResultSizeDataAccessException with the message '[N] users found with name X, expected 1'. This guards the invariant that usernames are unique in the users table, since duplicate rows make 'does this user exist' and subsequent loads ambiguous.
Solutions
- Add a UNIQUE constraint (or PRIMARY KEY) on the username column of the users table
- Deduplicate existing rows: DELETE duplicates keeping one row per username
- Ensure the configured users-by-username query cannot return more than one row per user (add filters/limits as appropriate)
- Catch IncorrectResultSizeDataAccessException around userExists if duplicates are legitimately possible in your environment
Example fix
// before -- no constraint, duplicate usernames possible CREATE TABLE users(username VARCHAR(50), ...); // after CREATE TABLE users(username VARCHAR(50) NOT NULL PRIMARY KEY, ...);
Defensive patterns
Strategy: try-catch
Validate before calling
Integer count = jdbcTemplate.queryForObject(
"SELECT COUNT(*) FROM users WHERE username = ?", Integer.class, username);
if (count != null && count > 1) {
throw new IllegalStateException("Duplicate username rows in users table: " + username);
} Try / catch
try {
return manager.userExists(username);
} catch (IncorrectResultSizeDataAccessException e) {
// duplicates detected: trigger data-cleanup/ops alert
return false;
} Prevention
- Enforce a UNIQUE/PK constraint on the users.username column
- Deduplicate and validate seed/migration scripts before running them
- Keep the custom users-by-username query returning at most one row per user
- Monitor for IncorrectResultSizeDataAccessException as a data-integrity signal
When it happens
Trigger: The users table contains duplicate rows for the same username (missing unique constraint on the username column); running against a schema where users is duplicated by joins or seeding scripts inserted the user twice; query configured via setUsersByUsernameQuery returning multiple rows per user.
Common situations: Manual data migration or fixtures inserting the same username twice; schemas missing PRIMARY KEY/UNIQUE on username; multi-tenant tables queried without tenant filtering in the custom query.
Understand the failure class
Background: Database query failed: Internal Server Error 500s wrapping SQL, Prisma, and connection failures — what to check first — this error's family across 16 libraries.
Related errors
- Could not find required group 'X'
- Autologin failed due to data access problem
- Can't change password as no Authentication object found in…
- Failed to deserialize asserting party credential collection
- JdbcDaoImpl.noAuthority
AI-assisted analysis of spring-projects/spring-security@96852e8860 (2026-09-10).
Data as JSON: /api/errors/ea7b4fdbf5aaec7c.
Report an issue: GitHub.
Appendix: source
Thrown at core/src/main/java/org/springframework/security/provisioning/JdbcUserDetailsManager.java:355
context.setAuthentication(authentication);
this.securityContextHolderStrategy.setContext(context);
this.userCache.removeUserFromCache(username);
}
protected Authentication createNewAuthentication(Authentication currentAuth, @Nullable String newPassword) {
UserDetails user = loadUserByUsername(currentAuth.getName());
UsernamePasswordAuthenticationToken newAuthentication = UsernamePasswordAuthenticationToken.authenticated(user,
null, user.getAuthorities());
newAuthentication.setDetails(currentAuth.getDetails());
return newAuthentication;
}
@Override
public boolean userExists(String username) {
@SuppressWarnings("ConstantConditions")
Integer usersCount = requireJdbcTemplate().queryForObject(this.userExistsSql, Integer.class, username);
if (usersCount == null || usersCount > 1) {
throw new IncorrectResultSizeDataAccessException(
"[" + usersCount + "] users found with name '" + username + "', expected 1", 1);
}
return usersCount == 1;
}
@Override
public List<String> findAllGroups() {
// @formatter:off
return requireJdbcTemplate().queryForList(this.findAllGroupsSql, String.class)
.stream()
.filter(Objects::nonNull)
.collect(Collectors.toList());
// @formatter:on
}
@Override
public List<String> findUsersInGroup(String groupName) {
Assert.hasText(groupName, "groupName should have text");View on GitHub (pinned to 96852e8860)