spring-projects/spring-security · error · IllegalArgumentException
idPrefix {idPrefix} cannot contain idSuffix {idSuffix}
Error message
idPrefix {idPrefix} cannot contain idSuffix {idSuffix} What it means
The idPrefix (e.g. '{') and idSuffix (e.g. '}') delimit the encoder id in encoded passwords. If the prefix already contains the suffix as a substring, extracting the id would be ambiguous, so the constructor rejects the combination with this IllegalArgumentException.
Source
Thrown at crypto/src/main/java/org/springframework/security/crypto/password/DelegatingPasswordEncoder.java:189
* @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);
}
if (id.contains(idSuffix)) {
throw new IllegalArgumentException("id " + id + " cannot contain " + idSuffix);
}
}
this.idForEncode = idForEncode;View on GitHub (pinned to 96852e8860)
Solutions
- Choose non-overlapping delimiters, keeping the default idPrefix="{" and idSuffix="}"
- Log the two values before construction and verify neither is a substring of the other
- Revert to PasswordEncoderFactories.createDelegatingPasswordEncoder() if custom delimiters are not actually needed
Example fix
// before
new DelegatingPasswordEncoder("bcrypt", encoders, "{", "{");
// after
new DelegatingPasswordEncoder("bcrypt", encoders, "{", "}"); Defensive patterns
Strategy: validation
Validate before calling
if (idPrefix != null && idSuffix != null && idPrefix.contains(idSuffix)) {
throw new IllegalStateException("idPrefix must not contain idSuffix");
} Try / catch
try {
return new DelegatingPasswordEncoder(idForEncode, encoders, idPrefix, idSuffix);
} catch (IllegalArgumentException e) {
throw new ConfigurationException("Bad prefix/suffix delimiters: " + e.getMessage(), e);
} Prevention
- Stick to the default '{' and '}' delimiters
- Assert prefix and suffix are distinct, non-overlapping strings in config validation
When it happens
Trigger: Invoking the DelegatingPasswordEncoder constructor where idPrefix.contains(idSuffix) is true, e.g. prefix "{," suffix "," or prefix "{" and suffix "{{".
Common situations: Customizing the {id}password wrapping format with unusual delimiters and accidentally choosing overlapping strings; typos where both prefix and suffix are set to the same value.
Understand the failure class
Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.
Related errors
- suffix cannot be empty
- idForEncode {idForEncode}is not found in idToPasswordEncoder
- id {id} cannot contain {idPrefix}
- id {id} cannot contain {idSuffix}
- Unsupported implementation of Sid
AI-assisted analysis of spring-projects/spring-security@96852e8860 (2026-09-10).
Data as JSON: /api/errors/de52e83ab3354456.
Report an issue: GitHub.