{"record":{"id":"04507421e1302840","repo":"spring-projects/spring-security","slug":"encode-is-not-supported","errorCode":null,"errorMessage":"encode is not supported","messagePattern":"encode is not supported","errorType":"exception","errorClass":"UnsupportedOperationException","httpStatus":null,"severity":"error","filePath":"crypto/src/main/java/org/springframework/security/crypto/password/DelegatingPasswordEncoder.java","lineNumber":291,"sourceCode":"\t\t\tString encodedPassword = extractEncodedPassword(prefixEncodedPassword);\n\t\t\treturn this.passwordEncoderForEncode.upgradeEncoding(encodedPassword);\n\t\t}\n\t}\n\n\tprivate String extractEncodedPassword(String prefixEncodedPassword) {\n\t\tint start = prefixEncodedPassword.indexOf(this.idSuffix);\n\t\treturn prefixEncodedPassword.substring(start + this.idSuffix.length());\n\t}\n\n\t/**\n\t * Default {@link PasswordEncoder} that throws an exception telling that a suitable\n\t * {@link PasswordEncoder} for the id could not be found.\n\t */\n\tprivate class UnmappedIdPasswordEncoder extends AbstractValidatingPasswordEncoder {\n\n\t\t@Override\n\t\tprotected String encodeNonNullPassword(String rawPassword) {\n\t\t\tthrow new UnsupportedOperationException(\"encode is not supported\");\n\t\t}\n\n\t\t@Override\n\t\tprotected boolean matchesNonNull(String rawPassword, String prefixEncodedPassword) {\n\t\t\tString id = extractId(prefixEncodedPassword);\n\t\t\tif (id != null && !id.isBlank()) {\n\t\t\t\tthrow new IllegalArgumentException(String.format(NO_PASSWORD_ENCODER_MAPPED, id));\n\t\t\t}\n\t\t\tif (prefixEncodedPassword != null && !prefixEncodedPassword.isBlank()) {\n\t\t\t\tint start = prefixEncodedPassword.indexOf(DelegatingPasswordEncoder.this.idPrefix);\n\t\t\t\tint end = prefixEncodedPassword.indexOf(DelegatingPasswordEncoder.this.idSuffix, start);\n\t\t\t\tif (start < 0 && end < 0) {\n\t\t\t\t\tthrow new IllegalArgumentException(NO_PASSWORD_ENCODER_PREFIX);\n\t\t\t\t}\n\t\t\t}\n\t\t\tthrow new IllegalArgumentException(String.format(MALFORMED_PASSWORD_ENCODER_PREFIX,\n\t\t\t\t\tDelegatingPasswordEncoder.this.idPrefix, DelegatingPasswordEncoder.this.idSuffix));\n\t\t}","sourceCodeStart":273,"sourceCodeEnd":309,"githubUrl":"https://github.com/spring-projects/spring-security/blob/96852e8860138a482cb13d1479573f24ff6443c6/crypto/src/main/java/org/springframework/security/crypto/password/DelegatingPasswordEncoder.java#L273-L309","documentation":"UnmappedIdPasswordEncoder is the default matcher used when an encoded password's id has no registered delegate. Matching may be delegated to it, but encoding is meaningless (it would have to pick an arbitrary id), so encodeNonNullPassword unconditionally throws UnsupportedOperationException.","triggerScenarios":"Calling encode() on a DelegatingPasswordEncoder whose configured idForEncode resolves to the internal UnmappedIdPasswordEncoder — practically, calling encode on a misconstructed or misused delegating encoder rather than a real delegate.","commonSituations":"Reflection or framework code resolving the encoder by type and invoking encode without knowing it is the unmapped-id placeholder; custom subclassing that routes encoding through the fallback encoder.","solutions":["Encode via a real delegate encoder (e.g. BCryptPasswordEncoder) or ensure the DelegatingPasswordEncoder was built with a valid idForEncode registered in idToPasswordEncoder","Catch UnsupportedOperationException and route encoding to an actual encoder","Do not expose the UnmappedIdPasswordEncoder inner encoder as the encoding path in custom code"],"exampleFix":"// before\nString encoded = unmappedIdEncoder.encode(rawPassword); // throws\n// after\nString encoded = delegatingPasswordEncoder.encode(rawPassword); // uses idForEncode delegate\n","handlingStrategy":"try-catch","validationCode":"if (encoder instanceof DelegatingPasswordEncoder d) {\n    // ensure encoding goes through a real delegate, i.e. the encoder was built with a valid idForEncode\n}","typeGuard":"if (encoder instanceof DelegatingPasswordEncoder) {\n    // safe to encode(); the UnmappedId placeholder is internal and not normally exposed\n}","tryCatchPattern":"try {\n    encoded = encoder.encode(rawPassword);\n} catch (UnsupportedOperationException e) {\n    encoded = realDelegateEncoder.encode(rawPassword);\n}","preventionTips":["Only call encode() through a properly constructed DelegatingPasswordEncoder with a registered idForEncode","Do not reach into internal/fallback encoders via reflection"],"tags":["spring-security","unsupported-operation","password-encoding"],"backgroundTag":"unsupported-operation","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"}