spring-projects/spring-security · error · IllegalArgumentException
prefix cannot be null
Error message
prefix cannot be null
What it means
DelegatingPasswordEncoder's full constructor requires a non-null idPrefix (default "{") and throws IllegalArgumentException('prefix cannot be null') when it is null. The prefix/suffix delimit the encoder id inside encoded password strings and are needed to parse {id}... on matches().
Source
Thrown at crypto/src/main/java/org/springframework/security/crypto/password/DelegatingPasswordEncoder.java:183
}
/**
* Creates a new instance.
* @param idForEncode the id used to lookup which {@link PasswordEncoder} should be
* used for {@link #encode(CharSequence)}
* @param idToPasswordEncoder a Map of id to {@link PasswordEncoder} used to determine
* which {@link PasswordEncoder} should be used for
* @param idPrefix the prefix that denotes the start of the id in the encoded results
* @param idSuffix the suffix that denotes the end of an id in the encoded results
* {@link #matches(CharSequence, String)}
*/
public DelegatingPasswordEncoder(String idForEncode, Map<String, PasswordEncoder> idToPasswordEncoder,
String idPrefix, String idSuffix) {
if (idForEncode == null) {
throw new IllegalArgumentException("idForEncode cannot be null");
}
if (idPrefix == null) {
throw new IllegalArgumentException("prefix cannot be null");
}
if (idSuffix == null || idSuffix.isEmpty()) {
throw new IllegalArgumentException("suffix cannot be empty");
}
if (idPrefix.contains(idSuffix)) {
throw new IllegalArgumentException("idPrefix " + idPrefix + " cannot contain idSuffix " + idSuffix);
}
if (!idToPasswordEncoder.containsKey(idForEncode)) {
throw new IllegalArgumentException(
"idForEncode " + idForEncode + "is not found in idToPasswordEncoder " + idToPasswordEncoder);
}
for (String id : idToPasswordEncoder.keySet()) {
if (id == null) {
continue;
}
if (!idPrefix.isEmpty() && id.contains(idPrefix)) {
throw new IllegalArgumentException("id " + id + " cannot contain " + idPrefix);View on GitHub (pinned to 96852e8860)
Solutions
- Pass non-null delimiters, typically "{" and "}".
- To use no delimiters, pass empty strings where allowed, but note the suffix must be non-null and non-empty and the prefix must not contain the suffix.
- Validate configured delimiter values before constructing the encoder.
Example fix
// before
String prefix = props.get("pw.prefix"); // null
PasswordEncoder encoder = new DelegatingPasswordEncoder("bcrypt", encoders, prefix, "}");
// after
String prefix = props.getOrDefault("pw.prefix", "{");
PasswordEncoder encoder = new DelegatingPasswordEncoder("bcrypt", encoders, prefix, "}"); Defensive patterns
Strategy: validation
Validate before calling
if (idPrefix == null) {
throw new IllegalArgumentException("idPrefix must be non-null (default \"{\")");
}
if (idSuffix == null || idSuffix.isEmpty()) {
throw new IllegalArgumentException("idSuffix must be non-empty (default \"}\")");
}
PasswordEncoder encoder = new DelegatingPasswordEncoder(idForEncode, idToPasswordEncoder, idPrefix, idSuffix); Type guard
boolean areValidDelimiters(String prefix, String suffix) {
return prefix != null && suffix != null && !suffix.isEmpty() && !prefix.contains(suffix);
} Try / catch
try {
encoder = new DelegatingPasswordEncoder(idForEncode, idToPasswordEncoder, idPrefix, idSuffix);
} catch (IllegalArgumentException ex) {
encoder = new DelegatingPasswordEncoder(idForEncode, idToPasswordEncoder, "{", "}");
} Prevention
- Keep the standard delimiters { and } unless you control the entire stored-password format
- Default prefix/suffix from properties instead of letting missing keys inject null
- Remember related constraints: non-empty suffix and prefix must not contain suffix — validate all at once
- Test matches() on an existing stored password after changing delimiters to avoid lockouts
When it happens
Trigger: Calling new DelegatingPasswordEncoder(idForEncode, idToPasswordEncoder, null, "}") or passing a prefix variable that resolved to null; customizing delimiters and forgetting the prefix while setting the suffix.
Common situations: Externalizing prefix/suffix to properties where the prefix key is absent; intentionally wanting no prefix by passing null instead of an empty-safe value; copy-paste of the suffix argument into the prefix slot.
Related errors
- idForEncode cannot be null
- String cannot be null
- encode cannot be null
- Cannot pass null or empty values to constructor
- password cannot be more than 72 bytes
AI-assisted analysis of spring-projects/spring-security@96852e8860 (2026-09-10).
Data as JSON: /api/errors/720f531e6206cb4b.
Report an issue: GitHub.