apereo/cas · error · FailedLoginException
Missing field value 'total' from the query results for…
Error message
Missing field value 'total' from the query results for [username] or value not parseable as a number
What it means
After finding the 'total' column, the handler validates it is a parseable number; if the value is null or NumberUtils.isCreatable fails, it throws FailedLoginException('Missing field value 'total' ... or value not parseable as a number'). This guards the count-based authentication contract.
Solutions
- Ensure the query computes a real numeric count (COUNT(*)) and never returns NULL for total
- Wrap with COALESCE: SELECT COALESCE(COUNT(*),0) AS total ...
- Inspect the query result manually to see what value 'total' carries
- Fix alias collisions where 'total' maps to a text column
Example fix
// before // SELECT total FROM user_counts WHERE username=? -- text column // after // SELECT COUNT(*) AS total FROM users WHERE username=?
Defensive patterns
Strategy: validation
Validate before calling
Object total = jdbc.queryForMap(sql, user).get("total");
if (total == null || !NumberUtils.isCreatable(total.toString()))
throw new IllegalStateException("'total' must be a non-null numeric COUNT(*) value, got: " + total); Type guard
boolean isNumericCount(Object v) { return v != null && NumberUtils.isCreatable(v.toString()); } Try / catch
try {
authResult = handler.authenticate(credential);
} catch (FailedLoginException e) {
if (e.getMessage().contains("not parseable as a number")) {
log.error("'total' column is null/non-numeric; fix SQL to COUNT(*) AS total");
throw new ConfigurationException("Bad auth sql projection");
}
throw e;
} Prevention
- Use COALESCE(COUNT(*),0) AS total so NULL never appears
- Do not alias text columns as 'total'
- Keep the sql minimal: one numeric count projection
- Add a startup integration test asserting the total value is numeric
When it happens
Trigger: dbFields contains 'total' but its value is null, or its toString() is not numeric (e.g. empty string, 'NULL' literal, a non-numeric placeholder from the query).
Common situations: COALESCE/NULL result from an outer query, alias collides with a non-numeric column, driver returns the string 'NULL', SQL bug returns text instead of a count.
Related errors
- Missing field 'total' from the query results for [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/09893781548c3ade.
Report an issue: GitHub.
Appendix: source
Thrown at support/cas-server-support-jdbc-authentication/src/main/java/org/apereo/cas/jdbc/QueryDatabaseAuthenticationHandler.java:73
try {
val dbFields = query(credential);
if (dbFields.containsKey(properties.getFieldPassword())) {
val dbPassword = (String) dbFields.get(properties.getFieldPassword());
val originalPasswordMatchFails = StringUtils.isNotBlank(originalPassword) && !matches(originalPassword, dbPassword);
val originalPasswordEquals = StringUtils.isBlank(originalPassword) && !Strings.CI.equals(password, dbPassword);
if (originalPasswordMatchFails || originalPasswordEquals) {
throw new FailedLoginException("Password does not match value on record.");
}
} else {
LOGGER.debug("Password field is not found in the query results. Checking for result count...");
if (!dbFields.containsKey("total")) {
throw new FailedLoginException("Missing field 'total' from the query results for " + username);
}
val count = dbFields.get("total");
if (count == null || !NumberUtils.isCreatable(count.toString())) {
throw new FailedLoginException("Missing field value 'total' from the query results for "
+ username + " or value not parseable as a number");
}
val number = NumberUtils.createNumber(count.toString());
if (number.longValue() != 1) {
throw new FailedLoginException("No records found for user " + username);
}
}
if (StringUtils.isNotBlank(properties.getFieldDisabled()) && dbFields.containsKey(properties.getFieldDisabled())) {
val dbDisabled = dbFields.get(properties.getFieldDisabled()).toString();
if (BooleanUtils.toBoolean(dbDisabled) || "1".equals(dbDisabled)) {
throw new AccountDisabledException("Account has been disabled");
}
}
if (StringUtils.isNotBlank(properties.getFieldExpired()) && dbFields.containsKey(properties.getFieldExpired())) {
val dbExpired = dbFields.get(properties.getFieldExpired()).toString();
if (BooleanUtils.toBoolean(dbExpired) || "1".equals(dbExpired)) {View on GitHub (pinned to e7288fc434)