{"record":{"id":"bb92487d198bbf51","repo":"spring-projects/spring-security","slug":"invalid-algorithm-type-x","errorCode":null,"errorMessage":"Invalid algorithm type: X","messagePattern":"Invalid algorithm type: X","errorType":"exception","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"crypto/src/main/java/org/springframework/security/crypto/argon2/Argon2EncodingUtils.java","lineNumber":114,"sourceCode":"\t * output. Both are required. The binary salt length and the output length must be in\n\t * the allowed ranges defined in argon2.h.\n\t * @param encodedHash the Argon2 hash string as described above\n\t * @return an {@link Argon2Hash} object containing the raw hash and the\n\t * {@link Argon2Parameters}.\n\t * @throws IllegalArgumentException if the encoded hash is malformed\n\t */\n\tstatic Argon2Hash decode(String encodedHash) throws IllegalArgumentException {\n\t\tArgon2Parameters.Builder paramsBuilder;\n\t\tString[] parts = encodedHash.split(\"\\\\$\");\n\t\tif (parts.length < 4) {\n\t\t\tthrow new IllegalArgumentException(\"Invalid encoded Argon2-hash\");\n\t\t}\n\t\tint currentPart = 1;\n\t\tparamsBuilder = switch (parts[currentPart++]) {\n\t\t\tcase \"argon2d\" -> new Argon2Parameters.Builder(Argon2Parameters.ARGON2_d);\n\t\t\tcase \"argon2i\" -> new Argon2Parameters.Builder(Argon2Parameters.ARGON2_i);\n\t\t\tcase \"argon2id\" -> new Argon2Parameters.Builder(Argon2Parameters.ARGON2_id);\n\t\t\tdefault -> throw new IllegalArgumentException(\"Invalid algorithm type: \" + parts[1]);\n\t\t};\n\t\tif (parts[currentPart].startsWith(\"v=\")) {\n\t\t\tparamsBuilder.withVersion(Integer.parseInt(parts[currentPart].substring(2)));\n\t\t\tcurrentPart++;\n\t\t}\n\t\tString[] performanceParams = parts[currentPart++].split(\",\");\n\t\tif (performanceParams.length != 3) {\n\t\t\tthrow new IllegalArgumentException(\"Amount of performance parameters invalid\");\n\t\t}\n\t\tif (!performanceParams[0].startsWith(\"m=\")) {\n\t\t\tthrow new IllegalArgumentException(\"Invalid memory parameter\");\n\t\t}\n\t\tparamsBuilder.withMemoryAsKB(Integer.parseInt(performanceParams[0].substring(2)));\n\t\tif (!performanceParams[1].startsWith(\"t=\")) {\n\t\t\tthrow new IllegalArgumentException(\"Invalid iterations parameter\");\n\t\t}\n\t\tparamsBuilder.withIterations(Integer.parseInt(performanceParams[1].substring(2)));\n\t\tif (!performanceParams[2].startsWith(\"p=\")) {","sourceCodeStart":96,"sourceCodeEnd":132,"githubUrl":"https://github.com/spring-projects/spring-security/blob/96852e8860138a482cb13d1479573f24ff6443c6/crypto/src/main/java/org/springframework/security/crypto/argon2/Argon2EncodingUtils.java#L96-L132","documentation":"After splitting the encoded hash, decode() dispatches on the algorithm segment (parts[1]); only argon2d, argon2i, and argon2id are supported. Any other identifier — or an empty/garbled one — causes this IllegalArgumentException. The hash's algorithm token must match the PHC Argon2 spec.","triggerScenarios":"Calling decode() on a hash whose second '$'-delimited segment is not exactly \"argon2d\", \"argon2i\", or \"argon2id\" — e.g. a bcrypt '$2a$...' string, an scrypt or PBKDF2 hash, or a hash with a case mismatch like 'Argon2id'.","commonSituations":"Feeding non-Argon2 hashes to Argon2PasswordEncoder.matches() during a password-migration; hand-edited hash strings; case-sensitivity mistakes when normalizing hashes.","solutions":["Ensure the hash was produced by an Argon2 variant and its algorithm token is lowercase 'argon2id'/'argon2i'/'argon2d'","Use the correct decoder/encoder for the actual algorithm (e.g. BCryptPasswordEncoder for '$2a$' hashes)","During migrations, version-prefix stored hashes and dispatch to the right PasswordEncoder via DelegatingPasswordEncoder"],"exampleFix":"// before\nPasswordEncoder encoder = new Argon2PasswordEncoder(); // used on legacy bcrypt hashes\n// after\nPasswordEncoder encoder = PasswordEncoderFactories.createDelegatingPasswordEncoder(); // routes by {id} prefix","handlingStrategy":"validation","validationCode":"static boolean isArgon2Algorithm(String encodedHash) {\n    return encodedHash != null && encodedHash.startsWith(\"$argon2id$\") || encodedHash.startsWith(\"$argon2i$\") || encodedHash.startsWith(\"$argon2d$\");\n}","typeGuard":null,"tryCatchPattern":"try {\n    return Argon2EncodingUtils.decode(hash);\n} catch (IllegalArgumentException e) {\n    if (e.getMessage().startsWith(\"Invalid algorithm type\")) {\n        throw new UnsupportedHashAlgorithmException(hash, e);\n    }\n    throw e;\n}","preventionTips":["Use DelegatingPasswordEncoder so each hash is decoded by its matching encoder","Keep algorithm tokens lowercase as per the PHC string format","Detect legacy hash types at login time and re-encode with Argon2 on success"],"tags":["argon2","unsupported-algorithm","password-hashing","java","spring-security"],"backgroundTag":"invalid-enum-value","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"}