spring-projects/spring-security · error · IllegalArgumentException
id {id} cannot contain {idSuffix}
Error message
id {id} cannot contain {idSuffix} What it means
For the same reason as the prefix check, an encoder id containing the idSuffix (e.g. '}') would break extraction of the id from '{id}encodedPassword'. The constructor throws this IllegalArgumentException when any map key contains the suffix.
Source
Thrown at crypto/src/main/java/org/springframework/security/crypto/password/DelegatingPasswordEncoder.java:204
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;
this.passwordEncoderForEncode = idToPasswordEncoder.get(idForEncode);
this.idToPasswordEncoder = new HashMap<>(idToPasswordEncoder);
this.idPrefix = idPrefix;
this.idSuffix = idSuffix;
}
/**
* Sets the {@link PasswordEncoder} to delegate to for
* {@link #matches(CharSequence, String)} if the id is not mapped to a
* {@link PasswordEncoder}.
*
* <p>
* The encodedPassword provided will be the full password passed in including the
* {"id"} portion.* For example, if the password of "{notmapped}foobar" was used, the
* "id" would be "notmapped" and the encodedPassword passed into theView on GitHub (pinned to 96852e8860)
Solutions
- Sanitize encoder ids to exclude the idSuffix (and idPrefix) characters before registering them
- Use plain alphanumeric ids for encoders
- Validate with id.contains(idSuffix) yourself in configuration code before constructing the delegating encoder
Example fix
// before
encoders.put("bcrypt}", new BCryptPasswordEncoder());
// after
encoders.put("bcrypt", new BCryptPasswordEncoder()); Defensive patterns
Strategy: validation
Validate before calling
for (String id : encoders.keySet()) {
if (id != null && id.contains("}")) {
throw new IllegalStateException("Encoder id must not contain '}': " + id);
}
} Try / catch
try {
return new DelegatingPasswordEncoder(idForEncode, encoders, "{", "}");
} catch (IllegalArgumentException e) {
log.error("Encoder id conflicts with prefix/suffix: {}", e.getMessage());
throw e;
} Prevention
- Sanitize encoder ids with id.replace("}", "") or reject them at config load time
- Use only letters, digits and hyphens in encoder ids
When it happens
Trigger: Registering an encoder id in idToPasswordEncoder whose key contains the idSuffix string, e.g. key "bc}rypt" with idSuffix "}".
Common situations: Dynamically generated ids that embed delimiter characters; pasting encoded-password fragments as ids; config-provided encoder names containing '}'.
Understand the failure class
Background: "invalid id" errors: invalid identifier format — why libraries reject IDs before lookup, and how to fix them — this error's family across 37 libraries.
Related errors
- id {id} cannot contain {idPrefix}
- suffix cannot be empty
- idPrefix {idPrefix} cannot contain idSuffix {idSuffix}
- idForEncode {idForEncode}is not found in idToPasswordEncoder
- Unsupported implementation of Sid
AI-assisted analysis of spring-projects/spring-security@96852e8860 (2026-09-10).
Data as JSON: /api/errors/57f47c6275ff9f98.
Report an issue: GitHub.