alibaba/spring-ai-alibaba · error · IllegalArgumentException

Invalid encoded Argon2-hash

Error message

Invalid encoded Argon2-hash

What it means

PasswordCryptUtils.match verifies a plaintext password against an Argon2-encoded hash by splitting the encoded string on '$'. If the encoded password has fewer than 4 '$'-separated parts, it is not a valid Argon2 PHC-style string and an IllegalArgumentException("Invalid encoded Argon2-hash") is thrown.

Source

Thrown at spring-ai-alibaba-admin/spring-ai-alibaba-admin-server-core/src/main/java/com/alibaba/cloud/ai/studio/core/utils/security/PasswordCryptUtils.java:94

			.append(params.getLanes())
			.append("$")
			.append(b64encoder.encodeToString(salt))
			.append("$")
			.append(b64encoder.encodeToString(hash));
		return stringBuilder.toString();
	}

	/**
	 * Verifies if a password matches the encoded password.
	 * @param password The password to verify
	 * @param encodedPassword The encoded password to check against
	 * @return true if the password matches, false otherwise
	 * @throws IllegalArgumentException if the encoded password format is invalid
	 */
	public static boolean match(String password, String encodedPassword) {
		String[] parts = encodedPassword.split("\\$");
		if (parts.length < 4) {
			throw new IllegalArgumentException("Invalid encoded Argon2-hash");
		}

		Argon2Parameters.Builder builder = new Argon2Parameters.Builder(Argon2Parameters.ARGON2_id);

		if (parts[2].startsWith("$v=")) {
			int version = Integer.parseInt(parts[0].substring(2));
			builder.withVersion(version);
		}

		String[] perfParams = parts[3].split(",");
		if (perfParams.length != 3) {
			throw new IllegalArgumentException("Amount of performance parameters invalid");
		}

		if (!perfParams[0].startsWith("m=")) {
			throw new IllegalArgumentException("Invalid memory parameter");
		}
		builder.withMemoryAsKB(Integer.parseInt(perfParams[0].substring(2)));

View on GitHub (pinned to f82da0b50f)

Solutions

  1. Inspect the stored value; re-hash passwords with PasswordCryptUtils for accounts with malformed hashes
  2. Add a migration that resets or lazily re-hashes non-Argon2 stored credentials
  3. Validate the hash format (starts with $argon2 and has >=4 '$'-parts) before calling match, and treat invalid as login failure
  4. Check for DB-level corruption/truncation (column width, encoding) if many rows fail

Example fix

// before
boolean ok = PasswordCryptUtils.match(raw, user.getPassword()); // may throw
// after
String stored = user.getPassword();
boolean ok = stored != null && stored.startsWith("$argon2") && stored.split("\\$").length >= 4
        && PasswordCryptUtils.match(raw, stored);
Defensive patterns

Strategy: validation

Validate before calling

boolean isArgon2Hash(String stored) {
    return stored != null && stored.startsWith("$") && stored.split("\\$").length >= 4;
}

Try / catch

try {
    boolean ok = PasswordCryptUtils.match(raw, stored);
} catch (IllegalArgumentException e) {
    // treat malformed hash as authentication failure and flag the account for re-hash
    ok = false;
}

Prevention

When it happens

Trigger: Calling PasswordCryptUtils.match(password, encodedPassword) where encodedPassword is null-safe but malformed: plaintext stored instead of a hash, truncated hash, a bcrypt/MD5 hash passed in, or a hash corrupted by DB migration/trimming.

Common situations: Legacy user rows whose password column predates Argon2; seeds/fixtures with fake strings like "password123"; copy-paste truncation; switching hashing algorithms without a migration path.

Understand the failure class

Background: "Invalid ... format", "must be in format X", "does not look like a ..." — invalid argument format errors across CLI tools and libraries — this error's family across 17 libraries.

Related errors


AI-assisted analysis of alibaba/spring-ai-alibaba@f82da0b50f (2026-09-09). Data as JSON: /api/errors/04bf3eb2f79426fe. Report an issue: GitHub.