apereo/cas · error · AccountNotFoundException
Encoded password is null.
Error message
Encoded password is null.
What it means
transformPassword throws AccountNotFoundException when the configured PasswordEncoder encodes the password into a null/empty string. The raw password existed, but the encoding step produced nothing, so CAS reports the account as not found rather than continuing with an unusable encoded value.
Solutions
- Inspect the configured PasswordEncoder; ensure its encode() never returns null/empty — return the input or throw a clear error instead.
- Test the encoder directly in a unit test with the same password value.
- If using a Groovy/scripted encoder, add explicit return statements and logging inside the script.
- Verify the encoder bean binding on the handler (passwordEncoder field) points to the intended implementation.
- Check for character-encoding/array-conversion issues in custom encoder code.
Example fix
// before
public String encode(CharSequence raw) {
try { return sha256(raw); } catch (Exception e) { return null; }
}
// after
public String encode(CharSequence raw) {
try { return sha256(raw); } catch (Exception e) { throw new IllegalStateException("password encoding failed", e); }
} Defensive patterns
Strategy: validation
Validate before calling
// verify your encoder before wiring it
PasswordEncoder enc = ...;
String encoded = enc.encode("sample-password");
if (StringUtils.isBlank(encoded)) { throw new IllegalStateException("PasswordEncoder must never return a blank value"); } Try / catch
try {
return handler.authenticate(credential, service);
} catch (AccountNotFoundException e) {
if (e.getMessage() != null && e.getMessage().contains("Encoded password")) {
LOGGER.error("PasswordEncoder returned a blank value; fix or replace the encoder", e);
}
throw new BadCredentialsAuthenticationException();
} Prevention
- Unit test custom/scripted PasswordEncoders for null/empty return paths.
- Throw a descriptive exception from encode() rather than returning null on internal failure.
- Pin and review the encoder bean assignment after configuration refactors.
When it happens
Trigger: transformPassword calls passwordEncoder.encode(userPass.toPassword()) and the result is blank — e.g. a custom PasswordEncoder whose encode() returns null, a Groovy/scripted encoder that fails silently, or an encoder misconfigured with an empty format.
Common situations: Custom PasswordEncoder implementation bug (returning null on certain inputs); scripted encoder throwing internally and being swallowed; char array-to-string conversion wiping the value; encoder bean wired to the wrong implementation after a config refactor.
Related errors
- Authentication handler is disabled
- No user can be accepted because none is defined
- not found in backing map.
- Unable to authenticate
- No authentication handlers could be resolved to support the…
AI-assisted analysis of apereo/cas@e7288fc434 (2026-09-08).
Data as JSON: /api/errors/507668b091db1755.
Report an issue: GitHub.
Appendix: source
Thrown at core/cas-server-core-authentication-api/src/main/java/org/apereo/cas/authentication/handler/support/AbstractUsernamePasswordAuthenticationHandler.java:88
@Override
protected AuthenticationHandlerExecutionResult doAuthentication(final Credential credential, final Service service) throws Throwable {
val originalUserPass = (UsernamePasswordCredential) credential;
val userPass = new UsernamePasswordCredential();
FunctionUtils.doUnchecked(_ -> BeanUtils.copyProperties(userPass, originalUserPass));
transformUsername(userPass);
transformPassword(userPass);
LOGGER.debug("Attempting authentication internally for transformed credential [{}]", userPass);
return authenticateUsernamePasswordInternal(userPass, originalUserPass.toPassword());
}
protected void transformPassword(final UsernamePasswordCredential userPass) throws FailedLoginException, AccountNotFoundException {
if (StringUtils.isBlank(userPass.toPassword())) {
throw new FailedLoginException("Password is null.");
}
LOGGER.debug("Attempting to encode credential password via [{}] for [{}]", passwordEncoder.getClass().getName(), userPass.getUsername());
val transformedPsw = passwordEncoder.encode(userPass.toPassword());
if (StringUtils.isBlank(transformedPsw)) {
throw new AccountNotFoundException("Encoded password is null.");
}
userPass.assignPassword(transformedPsw);
}
/**
* Authenticates a username/password credential by an arbitrary strategy with extra parameter original credential password before
* encoding password. Override it if implementation need to use original password for authentication.
*
* @param credential the credential object bearing the transformed username and password.
* @param originalPassword original password from credential before password encoding
* @return AuthenticationHandlerExecutionResult resolved from credential on authentication success or null if no principal could be resolved from the credential.
* @throws Throwable the throwable
*/
protected abstract AuthenticationHandlerExecutionResult authenticateUsernamePasswordInternal(
UsernamePasswordCredential credential,
@Nullable String originalPassword) throws Throwable;
/**View on GitHub (pinned to e7288fc434)