spring-projects/spring-security · error · EmptyResultDataAccessException
Could not find required group 'X'
Error message
Could not find required group 'X'
What it means
JdbcUserDetailsManager.findGroupId resolves a group name to its numeric id using findGroupIdSql; when the query returns null (no row found) it throws EmptyResultDataAccessException('Could not find required group X', 1). This is called from group management operations (adding users to groups, reading group authorities) whenever the referenced group does not exist in the groups table.
Solutions
- Create the group first (JdbcUserDetailsManager.createGroup or equivalent insert into groups) before referencing it
- Verify the group name spelling and case against the groups table contents
- Run Spring Security's default group schema DDL (create_groups.sql) if the tables are missing
- Check findGroupIdSql (setFindGroupIdQuery) points at the correct table/column if using a custom schema
Example fix
// before
manager.addUserToGroup(username, "ADMINS"); // group missing -> EmptyResultDataAccessException
// after
if (manager.findAllGroups().stream().noneMatch("ADMINS"::equals)) {
manager.createGroup("ADMINS", AuthorityUtils.createAuthorityList("ROLE_ADMIN"));
}
manager.addUserToGroup(username, "ADMINS"); Defensive patterns
Strategy: validation
Validate before calling
boolean exists = manager.findAllGroups().stream()
.anyMatch(g -> g.equals(groupName));
if (!exists) {
throw new IllegalArgumentException("Group not found: " + groupName);
} Try / catch
try {
manager.addUserToGroup(username, groupName);
} catch (EmptyResultDataAccessException e) {
if (e.getMessage() != null && e.getMessage().startsWith("Could not find required group")) {
manager.createGroup(groupName, AuthorityUtils.NO_AUTHORITIES);
manager.addUserToGroup(username, groupName);
} else { throw e; }
} Prevention
- Create groups (createGroup) before referencing them in group operations
- Run Spring Security's groups schema DDL and seed data idempotently
- Match group-name casing exactly as stored
- Verify setFindGroupIdQuery targets the right table if using a custom schema
When it happens
Trigger: Calling renameGroup, addUserToGroup, removeUserFromGroup, or findGroupAuthorities with a group name absent from the groups table; referencing groups created by a different schema/prefix; case mismatch between the group name string and the stored value.
Common situations: Spring Security group-authority schema (groups, group_authorities, group_members) not initialized or dropped; environments where groups were seeded manually with different names; tests reusing hardcoded group names that no DB seeding created.
Understand the failure class
Background: Record Not Found Errors: "not found", RecordNotFound, and "was not found" — what they mean and how to fix them — this error's family across 28 libraries.
Related errors
- [N] users found with name 'X', expected 1
- 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/0c04036ed3449bdb.
Report an issue: GitHub.
Appendix: source
Thrown at core/src/main/java/org/springframework/security/provisioning/JdbcUserDetailsManager.java:483
});
}
@Override
public void addGroupAuthority(final String groupName, final GrantedAuthority authority) {
this.logger.debug("Adding authority '" + authority + "' to group '" + groupName + "'");
Assert.hasText(groupName, "groupName should have text");
Assert.notNull(authority, "authority cannot be null");
int id = findGroupId(groupName);
requireJdbcTemplate().update(this.insertGroupAuthoritySql, (ps) -> {
ps.setInt(1, id);
ps.setString(2, authority.getAuthority());
});
}
private int findGroupId(String group) {
Integer groupId = requireJdbcTemplate().queryForObject(this.findGroupIdSql, Integer.class, group);
if (groupId == null) {
throw new EmptyResultDataAccessException("Could not find required group '" + group + "'", 1);
}
return groupId;
}
private JdbcTemplate requireJdbcTemplate() {
JdbcTemplate jdbc = getJdbcTemplate();
Assert.notNull(jdbc, "JdbcTemplate cannot be null");
return jdbc;
}
/**
* Sets the {@link SecurityContextHolderStrategy} to use. The default action is to use
* the {@link SecurityContextHolderStrategy} stored in {@link SecurityContextHolder}.
*
* @since 5.8
*/
public void setSecurityContextHolderStrategy(SecurityContextHolderStrategy securityContextHolderStrategy) {
Assert.notNull(securityContextHolderStrategy, "securityContextHolderStrategy cannot be null");View on GitHub (pinned to 96852e8860)