{"record":{"id":"6883ffb2542d5b2e","repo":"spring-projects/spring-security","slug":"invalid-algorithm-type-n","errorCode":null,"errorMessage":"Invalid algorithm type: N","messagePattern":"Invalid algorithm type: N","errorType":"exception","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"crypto/src/main/java/org/springframework/security/crypto/argon2/Argon2EncodingUtils.java","lineNumber":65,"sourceCode":"\t *\n\t * where {@code <T>} is either 'd', 'id', or 'i', {@code <num>} is a decimal integer\n\t * (positive, fits in an 'unsigned long'), and {@code <bin>} is Base64-encoded data\n\t * (no '=' padding characters, no newline or whitespace).\n\t *\n\t * The last two binary chunks (encoded in Base64) are, in that order, the salt and the\n\t * output. If no salt has been used, the salt will be omitted.\n\t * @param hash the raw Argon2 hash in binary format\n\t * @param parameters the Argon2 parameters that were used to create the hash\n\t * @return the encoded Argon2-hash-string as described above\n\t * @throws IllegalArgumentException if the Argon2Parameters are invalid\n\t */\n\tstatic String encode(byte[] hash, Argon2Parameters parameters) throws IllegalArgumentException {\n\t\tStringBuilder stringBuilder = new StringBuilder();\n\t\tString type = switch (parameters.getType()) {\n\t\t\tcase Argon2Parameters.ARGON2_d -> \"$argon2d\";\n\t\t\tcase Argon2Parameters.ARGON2_i -> \"$argon2i\";\n\t\t\tcase Argon2Parameters.ARGON2_id -> \"$argon2id\";\n\t\t\tdefault -> throw new IllegalArgumentException(\"Invalid algorithm type: \" + parameters.getType());\n\t\t};\n\t\tstringBuilder.append(type);\n\t\tstringBuilder.append(\"$v=\")\n\t\t\t.append(parameters.getVersion())\n\t\t\t.append(\"$m=\")\n\t\t\t.append(parameters.getMemory())\n\t\t\t.append(\",t=\")\n\t\t\t.append(parameters.getIterations())\n\t\t\t.append(\",p=\")\n\t\t\t.append(parameters.getLanes());\n\t\tif (parameters.getSalt() != null) {\n\t\t\tstringBuilder.append(\"$\").append(b64encoder.encodeToString(parameters.getSalt()));\n\t\t}\n\t\tstringBuilder.append(\"$\").append(b64encoder.encodeToString(hash));\n\t\treturn stringBuilder.toString();\n\t}\n\n\t/**","sourceCodeStart":47,"sourceCodeEnd":83,"githubUrl":"https://github.com/spring-projects/spring-security/blob/96852e8860138a482cb13d1479573f24ff6443c6/crypto/src/main/java/org/springframework/security/crypto/argon2/Argon2EncodingUtils.java#L47-L83","documentation":"Argon2EncodingUtils.encode serializes an Argon2 hash plus parameters into the PHC modular-crypt string format; the Argon2 variant (type) must be one of ARGON2_d, ARGON2_i, or ARGON2_id. Any other integer type value hits the switch default and throws IllegalArgumentException('Invalid algorithm type: N'), since there is no defined encoding prefix for it.","triggerScenarios":"Building Argon2Parameters with a type constant outside {ARGON2_d, ARGON2_i, ARGON2_id} (e.g., a hand-written integer or corrupted value) and then calling encode; decoding a hash string with an unknown variant earlier and re-encoding its parameters; passing parameters constructed by older/foreign code with different constants.","commonSituations":"Hand-rolling Argon2Parameters instead of using Argon2PasswordEncoder's defaults; interop with libraries whose type constants differ; corrupted stored parameter blobs being re-encoded.","solutions":["Set the type from the official constants: new Argon2Parameters.Builder(Argon2Parameters.ARGON2_id) (or ARGON2_d / ARGON2_i)","Prefer Argon2PasswordEncoder, which builds valid parameters internally, over calling Argon2EncodingUtils directly","Log/inspect parameters.getType() at construction to catch corrupted values early","If migrating hashes, map foreign variant labels ('argon2d'/'argon2i'/'argon2id') to the matching Spring constant before re-encoding"],"exampleFix":"// before\nArgon2Parameters params = new Argon2Parameters.Builder(7).build(); // invalid type\nArgon2EncodingUtils.encode(hash, params); // IllegalArgumentException\n// after\nArgon2Parameters params = new Argon2Parameters\n    .Builder(Argon2Parameters.ARGON2_id)\n    .withVersion(Argon2Parameters.ARGON2_VERSION_13)\n    .build();\nString encoded = Argon2EncodingUtils.encode(hash, params);","handlingStrategy":"validation","validationCode":"int type = parameters.getType();\nif (type != Argon2Parameters.ARGON2_d && type != Argon2Parameters.ARGON2_i\n        && type != Argon2Parameters.ARGON2_id) {\n    throw new IllegalArgumentException(\"Unsupported Argon2 type: \" + type);\n}","typeGuard":"static boolean isValidArgon2Type(int type) {\n    return type == Argon2Parameters.ARGON2_d\n        || type == Argon2Parameters.ARGON2_i\n        || type == Argon2Parameters.ARGON2_id;\n}","tryCatchPattern":"try {\n    return Argon2EncodingUtils.encode(hash, parameters);\n} catch (IllegalArgumentException e) {\n    if (e.getMessage() != null && e.getMessage().startsWith(\"Invalid algorithm type\")) {\n        // rebuild parameters with a valid type constant\n    } else { throw e; }\n}","preventionTips":["Always pass official Argon2Parameters constants, never arbitrary ints","Use Argon2PasswordEncoder instead of calling Argon2EncodingUtils directly","Assert the builder type right after constructing Argon2Parameters in tests","Map foreign-library variant labels to Spring constants during hash migration"],"tags":["argon2","password-hashing","invalid-enum","crypto"],"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-23T08:17:48.524Z"}