spring-projects/spring-security · error · IllegalArgumentException

Invalid algorithm type: N

Error message

Invalid algorithm type: N

What it means

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.

Solutions

  1. Set the type from the official constants: new Argon2Parameters.Builder(Argon2Parameters.ARGON2_id) (or ARGON2_d / ARGON2_i)
  2. Prefer Argon2PasswordEncoder, which builds valid parameters internally, over calling Argon2EncodingUtils directly
  3. Log/inspect parameters.getType() at construction to catch corrupted values early
  4. If migrating hashes, map foreign variant labels ('argon2d'/'argon2i'/'argon2id') to the matching Spring constant before re-encoding

Example fix

// before
Argon2Parameters params = new Argon2Parameters.Builder(7).build(); // invalid type
Argon2EncodingUtils.encode(hash, params); // IllegalArgumentException
// after
Argon2Parameters params = new Argon2Parameters
    .Builder(Argon2Parameters.ARGON2_id)
    .withVersion(Argon2Parameters.ARGON2_VERSION_13)
    .build();
String encoded = Argon2EncodingUtils.encode(hash, params);
Defensive patterns

Strategy: validation

Validate before calling

int type = parameters.getType();
if (type != Argon2Parameters.ARGON2_d && type != Argon2Parameters.ARGON2_i
        && type != Argon2Parameters.ARGON2_id) {
    throw new IllegalArgumentException("Unsupported Argon2 type: " + type);
}

Type guard

static boolean isValidArgon2Type(int type) {
    return type == Argon2Parameters.ARGON2_d
        || type == Argon2Parameters.ARGON2_i
        || type == Argon2Parameters.ARGON2_id;
}

Try / catch

try {
    return Argon2EncodingUtils.encode(hash, parameters);
} catch (IllegalArgumentException e) {
    if (e.getMessage() != null && e.getMessage().startsWith("Invalid algorithm type")) {
        // rebuild parameters with a valid type constant
    } else { throw e; }
}

Prevention

When it happens

Trigger: 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.

Common situations: Hand-rolling Argon2Parameters instead of using Argon2PasswordEncoder's defaults; interop with libraries whose type constants differ; corrupted stored parameter blobs being re-encoded.

Understand the failure class

Background: Invalid enum value errors: "Unknown type", "Invalid scope", "must be one of" — when a string is not on the library's allowed list — this error's family across 23 libraries.

Related errors


AI-assisted analysis of spring-projects/spring-security@96852e8860 (2026-09-10). Data as JSON: /api/errors/6883ffb2542d5b2e. Report an issue: GitHub.

Appendix: source

Thrown at crypto/src/main/java/org/springframework/security/crypto/argon2/Argon2EncodingUtils.java:65

	 *
	 * where {@code <T>} is either 'd', 'id', or 'i', {@code <num>} is a decimal integer
	 * (positive, fits in an 'unsigned long'), and {@code <bin>} is Base64-encoded data
	 * (no '=' padding characters, no newline or whitespace).
	 *
	 * The last two binary chunks (encoded in Base64) are, in that order, the salt and the
	 * output. If no salt has been used, the salt will be omitted.
	 * @param hash the raw Argon2 hash in binary format
	 * @param parameters the Argon2 parameters that were used to create the hash
	 * @return the encoded Argon2-hash-string as described above
	 * @throws IllegalArgumentException if the Argon2Parameters are invalid
	 */
	static String encode(byte[] hash, Argon2Parameters parameters) throws IllegalArgumentException {
		StringBuilder stringBuilder = new StringBuilder();
		String type = switch (parameters.getType()) {
			case Argon2Parameters.ARGON2_d -> "$argon2d";
			case Argon2Parameters.ARGON2_i -> "$argon2i";
			case Argon2Parameters.ARGON2_id -> "$argon2id";
			default -> throw new IllegalArgumentException("Invalid algorithm type: " + parameters.getType());
		};
		stringBuilder.append(type);
		stringBuilder.append("$v=")
			.append(parameters.getVersion())
			.append("$m=")
			.append(parameters.getMemory())
			.append(",t=")
			.append(parameters.getIterations())
			.append(",p=")
			.append(parameters.getLanes());
		if (parameters.getSalt() != null) {
			stringBuilder.append("$").append(b64encoder.encodeToString(parameters.getSalt()));
		}
		stringBuilder.append("$").append(b64encoder.encodeToString(hash));
		return stringBuilder.toString();
	}

	/**

View on GitHub (pinned to 96852e8860)