apereo/cas · error · AccountNotFoundException
[username] not found with SQL query
Error message
[username] not found with SQL query
What it means
When the configured SQL query returns zero rows, Spring's IncorrectResultSizeDataAccessException with actualSize 0 is caught and rethrown as AccountNotFoundException('[username] not found with SQL query'). The username has no record in the table the query targets.
Solutions
- Run the SQL manually with the failing username to confirm zero rows
- Verify the user exists in the configured database/table and correct the username or data source
- Check sql config (cas.authn.jdbc.encode[0].sql) targets the right table and uses the right username placeholder
- Handle AccountNotFoundException in the auth flow with a user-friendly 'unknown user' message
Example fix
// before // cas.authn.jdbc.encode[0].sql=SELECT * FROM users WHERE LOWER(email)=LOWER(?) // user stored with local-part usernames // after // cas.authn.jdbc.encode[0].sql=SELECT * FROM users WHERE username=?
Defensive patterns
Strategy: try-catch
Validate before calling
int count = jdbc.queryForObject("SELECT COUNT(*) FROM users WHERE username=?", Integer.class, username);
if (count == 0) return showUnknownUserOrRegisterFlow(username); Try / catch
try {
authResult = handler.authenticate(credential);
} catch (AccountNotFoundException e) {
// no row matched; show generic invalid-credentials to avoid user enumeration
throw new BadCredentialsException("Invalid credentials");
} Prevention
- Test the configured sql manually with representative usernames
- Decide and document case-sensitivity/email-vs-username conventions
- Ensure the user is provisioned into the auth database before first login
- Return generic error text publicly to prevent username enumeration
When it happens
Trigger: performSqlQuery(username) returns no rows (singleRowSqlQuery / queryAndEncode flow) for the submitted username, causing EmptyResultDataAccessException translated to IncorrectResultSizeDataAccessException with getActualSize()==0.
Common situations: User typo or wrong username format (email vs local part), user absent from the auth database (exists only in another source), case-sensitivity mismatch in SQL, wrong table/schema/database configured.
Understand the failure class
Background: "User not found", "Invalid user", and "does not exist": what missing-user lookup errors mean across Rocket.Chat, LiteLLM, Phabricator, rustfs, and pnpm — this error's family across 10 libraries.
Related errors
- No records found for user [username]
- Principal attribute [
- [e.getMessage()]
- Password does not match value on record.
- Password has expired
AI-assisted analysis of apereo/cas@e7288fc434 (2026-09-08).
Data as JSON: /api/errors/1998ddca5983c000.
Report an issue: GitHub.
Appendix: source
Thrown at support/cas-server-support-jdbc-authentication/src/main/java/org/apereo/cas/jdbc/QueryAndEncodeDatabaseAuthenticationHandler.java:77
}
if (StringUtils.isNotBlank(properties.getExpiredFieldName()) && sqlQueryResults.containsKey(properties.getExpiredFieldName())) {
val dbExpired = sqlQueryResults.get(properties.getExpiredFieldName()).toString();
if (BooleanUtils.toBoolean(dbExpired) || "1".equals(dbExpired)) {
throw new AccountPasswordMustChangeException("Password has expired");
}
}
if (StringUtils.isNotBlank(properties.getDisabledFieldName()) && sqlQueryResults.containsKey(properties.getDisabledFieldName())) {
val dbDisabled = sqlQueryResults.get(properties.getDisabledFieldName()).toString();
if (BooleanUtils.toBoolean(dbDisabled) || "1".equals(dbDisabled)) {
throw new AccountDisabledException("Account has been disabled");
}
}
val attributes = collectPrincipalAttributes(sqlQueryResults);
val principal = principalFactory.createPrincipal(username, attributes);
return createHandlerResult(transformedCredential, principal, new ArrayList<>());
} catch (final IncorrectResultSizeDataAccessException e) {
if (e.getActualSize() == 0) {
throw new AccountNotFoundException(username + " not found with SQL query");
}
throw new FailedLoginException("Multiple records found for " + username);
} catch (final DataAccessException e) {
throw new PreventedException(e);
}
}
protected Map<String, Object> performSqlQuery(final String username) {
return getJdbcTemplate().queryForMap(properties.getSql(), username);
}
}
View on GitHub (pinned to e7288fc434)