{"record":{"id":"a5fa41e02b5429a6","repo":"spring-projects/spring-security","slug":"idforencode-cannot-be-null","errorCode":null,"errorMessage":"idForEncode cannot be null","messagePattern":"idForEncode cannot be null","errorType":"exception","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"crypto/src/main/java/org/springframework/security/crypto/password/DelegatingPasswordEncoder.java","lineNumber":180,"sourceCode":"\t */\n\tpublic DelegatingPasswordEncoder(String idForEncode, Map<String, PasswordEncoder> idToPasswordEncoder) {\n\t\tthis(idForEncode, idToPasswordEncoder, DEFAULT_ID_PREFIX, DEFAULT_ID_SUFFIX);\n\t}\n\n\t/**\n\t * Creates a new instance.\n\t * @param idForEncode the id used to lookup which {@link PasswordEncoder} should be\n\t * used for {@link #encode(CharSequence)}\n\t * @param idToPasswordEncoder a Map of id to {@link PasswordEncoder} used to determine\n\t * which {@link PasswordEncoder} should be used for\n\t * @param idPrefix the prefix that denotes the start of the id in the encoded results\n\t * @param idSuffix the suffix that denotes the end of an id in the encoded results\n\t * {@link #matches(CharSequence, String)}\n\t */\n\tpublic DelegatingPasswordEncoder(String idForEncode, Map<String, PasswordEncoder> idToPasswordEncoder,\n\t\t\tString idPrefix, String idSuffix) {\n\t\tif (idForEncode == null) {\n\t\t\tthrow new IllegalArgumentException(\"idForEncode cannot be null\");\n\t\t}\n\t\tif (idPrefix == null) {\n\t\t\tthrow new IllegalArgumentException(\"prefix cannot be null\");\n\t\t}\n\t\tif (idSuffix == null || idSuffix.isEmpty()) {\n\t\t\tthrow new IllegalArgumentException(\"suffix cannot be empty\");\n\t\t}\n\t\tif (idPrefix.contains(idSuffix)) {\n\t\t\tthrow new IllegalArgumentException(\"idPrefix \" + idPrefix + \" cannot contain idSuffix \" + idSuffix);\n\t\t}\n\n\t\tif (!idToPasswordEncoder.containsKey(idForEncode)) {\n\t\t\tthrow new IllegalArgumentException(\n\t\t\t\t\t\"idForEncode \" + idForEncode + \"is not found in idToPasswordEncoder \" + idToPasswordEncoder);\n\t\t}\n\t\tfor (String id : idToPasswordEncoder.keySet()) {\n\t\t\tif (id == null) {\n\t\t\t\tcontinue;","sourceCodeStart":162,"sourceCodeEnd":198,"githubUrl":"https://github.com/spring-projects/spring-security/blob/96852e8860138a482cb13d1479573f24ff6443c6/crypto/src/main/java/org/springframework/security/crypto/password/DelegatingPasswordEncoder.java#L162-L198","documentation":"DelegatingPasswordEncoder's full constructor requires a non-null idForEncode — the id of the PasswordEncoder used for new encodes — and throws IllegalArgumentException('idForEncode cannot be null') when it is null. The id is used to look up the default encoder in the idToPasswordEncoder map and to tag encoded passwords ({id}...), so it is a mandatory constructor argument.","triggerScenarios":"Calling new DelegatingPasswordEncoder(null, idToPasswordEncoder, \"{\", \"}\") (or the 4-arg variant) with a null id; an id variable sourced from config/constant that resolved to null.","commonSituations":"Spring config property for the encode id missing and injecting null; refactoring PasswordEncoderFactories-style setup and dropping the \"bcrypt\" literal; programmatic bean creation with a null default encoder id.","solutions":["Pass a valid id such as \"bcrypt\" that exists as a key in the idToPasswordEncoder map.","Load the id from configuration with a non-null default (e.g. properties.getProperty(\"encoder.id\", \"bcrypt\")).","Prefer PasswordEncoderFactories.createDelegatingPasswordEncoder() when defaults suffice."],"exampleFix":"// before\nString id = properties.get(\"password.encoder.id\"); // null\nPasswordEncoder encoder = new DelegatingPasswordEncoder(id, encoders, \"{\", \"}\");\n// after\nString id = properties.getOrDefault(\"password.encoder.id\", \"bcrypt\");\nPasswordEncoder encoder = new DelegatingPasswordEncoder(id, encoders, \"{\", \"}\");","handlingStrategy":"validation","validationCode":"if (idForEncode == null || !idToPasswordEncoder.containsKey(idForEncode)) {\n    throw new IllegalArgumentException(\"idForEncode must be non-null and present in idToPasswordEncoder\");\n}\nPasswordEncoder encoder = new DelegatingPasswordEncoder(idForEncode, idToPasswordEncoder, \"{\", \"}\");","typeGuard":"boolean isValidEncodeId(String id, java.util.Map<String, PasswordEncoder> map) {\n    return id != null && map != null && map.containsKey(id);\n}","tryCatchPattern":"try {\n    encoder = new DelegatingPasswordEncoder(idForEncode, idToPasswordEncoder, \"{\", \"}\");\n} catch (IllegalArgumentException ex) {\n    encoder = PasswordEncoderFactories.createDelegatingPasswordEncoder(); // bcrypt default\n}","preventionTips":["Never pass config values straight through; default missing ids to \"bcrypt\"","Ensure idForEncode is also a key of idToPasswordEncoder (a separate constructor check will otherwise fail)","Prefer PasswordEncoderFactories.createDelegatingPasswordEncoder() over manual construction","Add a startup assertion that the configured encode id resolves to a registered encoder"],"tags":["password","encoding","null-argument","constructor"],"backgroundTag":"null-argument","analyzedSha":"96852e8860138a482cb13d1479573f24ff6443c6","analyzedAt":"2026-09-10T23:25:23.477Z","contentChangedAt":"2026-09-10T23:25:23.477Z","schemaVersion":2},"datasetVersion":"2026-09-14T16:17:12.679Z"}