spring-projects/spring-security · error · IllegalArgumentException
Given that there is no default password encoder configured…
Error message
Given that there is no default password encoder configured, each password must have a password encoding prefix. Please either prefix this password with '{noop}' or set a default password encoder in `DelegatingPasswordEncoder`. What it means
When matching, if the stored password contains neither the idPrefix nor the idSuffix, it carries no encoder id at all. With no default encoder configured for such raw-format passwords, DelegatingPasswordEncoder cannot pick a matcher and throws this IllegalArgumentException, suggesting '{noop}' prefixing or a default encoder.
Solutions
- Re-prefix stored passwords with their encoding id, e.g. '{noop}secret' or '{bcrypt}$2a$10$...'
- Call setDefaultPasswordEncoderForMatches(encoder) to handle unprefixed passwords (e.g. with a delegating NoOp or BCrypt default)
- Re-encode the stored credentials into the {id}... format via a data migration
- For dev/test data, insert passwords using the DelegatingPasswordEncoder's own encode() output
Example fix
// before
// stored: $2a$10$dXJ3SW6G7P50lGmMkkmwe.20cQQubK3.HZWzG3YB1tlRy.fqvM/BG
// after
// stored: {bcrypt}$2a$10$dXJ3SW6G7P50lGmMkkmwe.20cQQubK3.HZWzG3YB1tlRy.fqvM/BG
Defensive patterns
Strategy: validation
Validate before calling
if (storedPassword != null && !storedPassword.startsWith("{")) {
throw new IllegalStateException("Stored password lacks {id} prefix: " + storedPassword);
} Try / catch
try {
return encoder.matches(rawPassword, storedPassword);
} catch (IllegalArgumentException e) {
// fall back to legacy matching for unprefixed hashes
return legacyEncoder.matches(rawPassword, storedPassword);
} Prevention
- Migrate all stored passwords to the '{id}encodedPassword' format
- Set a default encoder via setDefaultPasswordEncoderForMatches for legacy/unprefixed values
- Re-encode credentials through the delegating encoder at import time
When it happens
Trigger: matches() with a password that is plain text or an unprefixed hash (e.g. old '$2a$10$...' BCrypt string without '{bcrypt}') on a DelegatingPasswordEncoder created without setDefaultPasswordEncoderForMatches.
Common situations: Migrating a legacy user store to Spring Security's delegating encoder; hand-inserted test users with raw '{noop}pass' missing; seeding data directly into the DB without the {id} wrapper.
Related errors
- The name of the password encoder is improperly formatted or…
- There is no password encoder mapped for the id
- A Bean named mvcHandlerMappingIntrospector of type…
- A Bean named mvcHandlerMappingIntrospector of type…
- A filter chain that matches any request
AI-assisted analysis of spring-projects/spring-security@96852e8860 (2026-09-10).
Data as JSON: /api/errors/6e7bac67d90552a2.
Report an issue: GitHub.
Appendix: source
Thrown at crypto/src/main/java/org/springframework/security/crypto/password/DelegatingPasswordEncoder.java:304
*/
private class UnmappedIdPasswordEncoder extends AbstractValidatingPasswordEncoder {
@Override
protected String encodeNonNullPassword(String rawPassword) {
throw new UnsupportedOperationException("encode is not supported");
}
@Override
protected boolean matchesNonNull(String rawPassword, String prefixEncodedPassword) {
String id = extractId(prefixEncodedPassword);
if (id != null && !id.isBlank()) {
throw new IllegalArgumentException(String.format(NO_PASSWORD_ENCODER_MAPPED, id));
}
if (prefixEncodedPassword != null && !prefixEncodedPassword.isBlank()) {
int start = prefixEncodedPassword.indexOf(DelegatingPasswordEncoder.this.idPrefix);
int end = prefixEncodedPassword.indexOf(DelegatingPasswordEncoder.this.idSuffix, start);
if (start < 0 && end < 0) {
throw new IllegalArgumentException(NO_PASSWORD_ENCODER_PREFIX);
}
}
throw new IllegalArgumentException(String.format(MALFORMED_PASSWORD_ENCODER_PREFIX,
DelegatingPasswordEncoder.this.idPrefix, DelegatingPasswordEncoder.this.idSuffix));
}
}
}
View on GitHub (pinned to 96852e8860)