apereo/cas · error · AccountNotFoundException
Could not locate account for
Error message
Could not locate account for ${username} What it means
RestAuthenticationHandler throws AccountNotFoundException when the remote REST authentication endpoint replies HTTP 404 NOT_FOUND. CAS treats this as 'no such user' rather than a password failure, which affects subsequent handler processing and lockout statistics.
Solutions
- Verify the user exists in the remote identity store
- Check cas.authn.rest.url for typos or a missing/renamed path segment
- Confirm the endpoint service is deployed and routed correctly (test with curl)
- If your API signals unknown users differently (e.g. 200 with empty body), adapt the endpoint or use a custom handler
Example fix
// before cas.authn.rest.url=https://api.example.com/authenicate // after (typo fixed) cas.authn.rest.url=https://api.example.com/authenticate
Defensive patterns
Strategy: try-catch
Validate before calling
// Sanity-check the configured URL resolves before auth flows run var code = new URL(restAuthUrl).openConnection().connect(); // and inspect response code
Type guard
boolean isNotFound(HttpResponse r) { return r != null && r.getCode() == 404; } Try / catch
try {
return restHandler.authenticate(credential);
} catch (AccountNotFoundException e) {
LOGGER.info("Unknown user: {}", e.getMessage());
throw e; // continue auth chain for other handlers if configured
} Prevention
- Pin and smoke-test cas.authn.rest.url in deployment checks
- Keep endpoint paths stable across API version upgrades
- Distinguish real unknown-user 404s from routing 404s in endpoint logs
- Register fallback handlers in the CAS auth chain for users not in the REST store
When it happens
Trigger: authenticateUsernamePasswordInternal calls the REST endpoint, which responds 404; the switch maps NOT_FOUND -> AccountNotFoundException.
Common situations: Username does not exist in the remote system; the endpoint URL path is wrong so every request 404s; a reverse proxy returned 404 because the backing service is down or routes changed after an upgrade.
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
- not found in backing map.
- Unable to accept response status
- No credentials can be extracted to authenticate the REST…
- Unable to extract credentials for multifactor authentication
- not found in backing file.
AI-assisted analysis of apereo/cas@e7288fc434 (2026-09-08).
Data as JSON: /api/errors/12923fe36eb07b1b.
Report an issue: GitHub.
Appendix: source
Thrown at support/cas-server-support-rest-authentication/src/main/java/org/apereo/cas/adaptors/rest/RestAuthenticationHandler.java:95
var response = (HttpResponse) null;
try {
val exec = HttpExecutionRequest
.builder()
.basicAuthUsername(credential.getUsername())
.basicAuthPassword(credential.toPassword())
.method(HttpMethod.valueOf(properties.getMethod().toUpperCase(Locale.ENGLISH)))
.url(SpringExpressionLanguageValueResolver.getInstance().resolve(properties.getUri()))
.httpClient(httpClient)
.build()
.withoutRetry();
response = HttpUtils.execute(exec);
val status = HttpStatus.resolve(Objects.requireNonNull(response).getCode());
return switch (Objects.requireNonNull(status)) {
case OK -> buildPrincipalFromResponse(credential, response);
case FORBIDDEN -> throw new AccountDisabledException("Could not authenticate forbidden account for " + credential.getUsername());
case UNAUTHORIZED -> throw new FailedLoginException("Could not authenticate account for " + credential.getUsername());
case NOT_FOUND -> throw new AccountNotFoundException("Could not locate account for " + credential.getUsername());
case LOCKED -> throw new AccountLockedException("Could not authenticate locked account for " + credential.getUsername());
case PRECONDITION_FAILED -> throw new AccountExpiredException("Could not authenticate expired account for " + credential.getUsername());
case PRECONDITION_REQUIRED -> throw new AccountPasswordMustChangeException("Account password must change for " + credential.getUsername());
default -> throw new FailedLoginException("Rest endpoint returned an unknown status code " + status + " for " + credential.getUsername());
};
} finally {
HttpUtils.close(response);
}
}
protected AuthenticationHandlerExecutionResult buildPrincipalFromResponse(
final UsernamePasswordCredential credential,
final HttpResponse response) throws Throwable {
try {
try (val content = ((HttpEntityContainer) response).getEntity().getContent()) {
val result = IOUtils.toString(content, StandardCharsets.UTF_8);
LOGGER.debug("REST authentication response received: [{}]", result);
val principalFromRest = MAPPER.readValue(result, Principal.class);View on GitHub (pinned to e7288fc434)