apereo/cas · error · FailedLoginException
throwable.getMessage()
Error message
throwable.getMessage()
What it means
The predefined-accounts JAAS login module wraps any failure of callbackHandler.handle() (which collects the username/password callbacks) into a FailedLoginException whose message is the underlying throwable's message. It fires when the callback handler cannot supply credentials — typically no NameCallback/PasswordCallback handler is wired or the caller aborted. The username/password then cannot be checked against the configured 'accounts' option.
Solutions
- Ensure a callback handler able to supply name/password callbacks is configured for this JAAS login module
- Check the underlying throwable message for the actual callback failure cause
- Verify the 'accounts' JAAS option format is account::password entries separated by commas
Defensive patterns
Strategy: try-catch
When it happens
Trigger: Thrown at core/cas-server-core-authentication-api/src/main/java/org/apereo/cas/authentication/handler/support/jaas/AccountsPreDefinedLoginModule.java:53 when the library encounters an invalid state.
Common situations: See trigger scenarios.
AI-assisted analysis of apereo/cas@e7288fc434 (2026-09-08).
Data as JSON: /api/errors/96691cd6d805fcfb.
Report an issue: GitHub.
Appendix: source
Thrown at core/cas-server-core-authentication-api/src/main/java/org/apereo/cas/authentication/handler/support/jaas/AccountsPreDefinedLoginModule.java:53
val providedAccounts = options.containsKey("accounts") ? options.get("accounts").toString() : null;
if (StringUtils.isNotBlank(providedAccounts)) {
val eachAccount = org.springframework.util.StringUtils.commaDelimitedListToSet(providedAccounts);
eachAccount.stream()
.map(account -> Splitter.on("::").splitToList(account))
.filter(results -> results.size() == 2)
.forEach(results -> accounts.put(results.getFirst(), results.get(1)));
}
}
@Override
public boolean login() throws LoginException {
val nameCallback = new NameCallback("username");
val passwordCallback = new PasswordCallback("password", false);
FunctionUtils.doAndHandle(_ -> {
callbackHandler.handle(new Callback[]{nameCallback, passwordCallback});
}, throwable -> {
throw new FailedLoginException(throwable.getMessage());
}).accept(nameCallback);
val username = nameCallback.getName();
if (accounts.containsKey(username)) {
val password = new String(passwordCallback.getPassword());
this.succeeded = accounts.get(username).equals(password);
subject.getPrincipals().add(new StaticPrincipal(username));
return true;
}
this.succeeded = false;
return false;
}
@Override
public boolean commit() {
return this.succeeded;
}
View on GitHub (pinned to e7288fc434)