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

  1. Run the SQL manually with the failing username to confirm zero rows
  2. Verify the user exists in the configured database/table and correct the username or data source
  3. Check sql config (cas.authn.jdbc.encode[0].sql) targets the right table and uses the right username placeholder
  4. 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

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


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)