{"record":{"id":"55037a6397441515","repo":"spring-projects/spring-security","slug":"defaultpasswordencoderformatches-cannot-be-null","errorCode":null,"errorMessage":"defaultPasswordEncoderForMatches cannot be null","messagePattern":"defaultPasswordEncoderForMatches cannot be null","errorType":"validation","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"crypto/src/main/java/org/springframework/security/crypto/password/DelegatingPasswordEncoder.java","lineNumber":230,"sourceCode":"\t}\n\n\t/**\n\t * Sets the {@link PasswordEncoder} to delegate to for\n\t * {@link #matches(CharSequence, String)} if the id is not mapped to a\n\t * {@link PasswordEncoder}.\n\t *\n\t * <p>\n\t * The encodedPassword provided will be the full password passed in including the\n\t * {\"id\"} portion.* For example, if the password of \"{notmapped}foobar\" was used, the\n\t * \"id\" would be \"notmapped\" and the encodedPassword passed into the\n\t * {@link PasswordEncoder} would be \"{notmapped}foobar\".\n\t * </p>\n\t * @param defaultPasswordEncoderForMatches the encoder to use. The default is to throw\n\t * an {@link IllegalArgumentException}\n\t */\n\tpublic void setDefaultPasswordEncoderForMatches(PasswordEncoder defaultPasswordEncoderForMatches) {\n\t\tif (defaultPasswordEncoderForMatches == null) {\n\t\t\tthrow new IllegalArgumentException(\"defaultPasswordEncoderForMatches cannot be null\");\n\t\t}\n\t\tthis.defaultPasswordEncoderForMatches = defaultPasswordEncoderForMatches;\n\t}\n\n\t@Override\n\tprotected String encodeNonNullPassword(String rawPassword) {\n\t\treturn this.idPrefix + this.idForEncode + this.idSuffix + this.passwordEncoderForEncode.encode(rawPassword);\n\t}\n\n\t@Override\n\tprotected boolean matchesNonNull(String rawPassword, String prefixEncodedPassword) {\n\t\tString id = extractId(prefixEncodedPassword);\n\t\tPasswordEncoder delegate = this.idToPasswordEncoder.get(id);\n\t\tif (delegate == null) {\n\t\t\treturn this.defaultPasswordEncoderForMatches.matches(rawPassword, prefixEncodedPassword);\n\t\t}\n\t\tString encodedPassword = extractEncodedPassword(prefixEncodedPassword);\n\t\treturn delegate.matches(rawPassword, encodedPassword);","sourceCodeStart":212,"sourceCodeEnd":248,"githubUrl":"https://github.com/spring-projects/spring-security/blob/96852e8860138a482cb13d1479573f24ff6443c6/crypto/src/main/java/org/springframework/security/crypto/password/DelegatingPasswordEncoder.java#L212-L248","documentation":"setDefaultPasswordEncoderForMatches chooses the PasswordEncoder used when an encoded password has no recognized id. Passing null removes that safety encoder and leaves matching without a fallback, so the setter rejects null with this IllegalArgumentException.","triggerScenarios":"Calling delegatingPasswordEncoder.setDefaultPasswordEncoderForMatches(null), often via a Spring bean property or @Value injection that resolves to null.","commonSituations":"Bean wiring where a PasswordEncoder dependency failed to inject and arrives null; property placeholders that resolve to nothing; explicitly trying to 'unset' the default encoder (unsupported — pass a real encoder).","solutions":["Pass a real PasswordEncoder instance, e.g. new UnmappedIdPasswordEncoder() style default or a BCryptPasswordEncoder, not null","Check bean wiring/properties so the argument cannot be null (e.g. ensure the referenced bean exists)","If you want the original throwing behavior, do not call the setter at all — the initial default already throws a descriptive IllegalArgumentException on unmapped ids"],"exampleFix":"// before\nencoder.setDefaultPasswordEncoderForMatches(null);\n// after\nencoder.setDefaultPasswordEncoderForMatches(new BCryptPasswordEncoder());","handlingStrategy":"type-guard","validationCode":"if (defaultEncoder == null) {\n    throw new IllegalArgumentException(\"defaultPasswordEncoderForMatches must not be null\");\n}\nencoder.setDefaultPasswordEncoderForMatches(defaultEncoder);","typeGuard":"if (!(candidate instanceof PasswordEncoder encoder)) {\n    throw new IllegalStateException(\"Expected non-null PasswordEncoder, got: \" + candidate);\n}","tryCatchPattern":null,"preventionTips":["Wire the default encoder as a Spring bean so injection never yields null","Never pass null intending to 'reset' the default — simply don't call the setter"],"tags":["spring-security","null-argument","password-encoding","setter-validation"],"backgroundTag":"null-argument","analyzedSha":"96852e8860138a482cb13d1479573f24ff6443c6","analyzedAt":"2026-09-10T23:25:23.477Z","contentChangedAt":"2026-09-10T23:25:23.477Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}