quarkusio/quarkus · error · IllegalArgumentException

Iteration count must be greater than zero

Error message

Iteration count must be greater than zero

What it means

BcryptUtil.bcryptHash(password, iterationCount, salt) validates arguments before delegating to Elytron's BCrypt PasswordFactory. It throws IllegalArgumentException when iterationCount is zero or negative, because bcrypt requires a positive work factor (Elytron uses it as the log-rounds parameter).

Source

Thrown at extensions/elytron-security-common/runtime/src/main/java/io/quarkus/elytron/security/common/BcryptUtil.java:66

        random.nextBytes(salt);
        return bcryptHash(password, iterationCount, salt);
    }

    /**
     * Produces a Modular Crypt Format bcrypt hash of the given password, using the specified salt and the specified iteration
     * count.
     *
     * @param password the password to hash
     * @param iterationCount the number of iterations to use while hashing
     * @param salt the salt to use while hashing
     * @return the Modular Crypt Format bcrypt hash of the given password
     * @throws NullPointerException if the password or salt are null
     * @throws IllegalArgumentException if the iterationCount parameter is negative or zero, or if the salt length is not equal
     *         to 16
     */
    public static String bcryptHash(String password, int iterationCount, byte[] salt) {
        if (iterationCount <= 0) {
            throw new IllegalArgumentException("Iteration count must be greater than zero");
        }
        Objects.requireNonNull(password, "password is required");
        Objects.requireNonNull(salt, "salt is required");
        if (salt.length != BCryptPassword.BCRYPT_SALT_SIZE) {
            throw new IllegalArgumentException("Salt length must be exactly " + BCryptPassword.BCRYPT_SALT_SIZE + " bytes");
        }

        PasswordFactory passwordFactory;
        try {
            passwordFactory = PasswordFactory.getInstance(BCryptPassword.ALGORITHM_BCRYPT, provider);
        } catch (NoSuchAlgorithmException e) {
            // can't really happen
            throw new RuntimeException(e);
        }

        IteratedSaltedPasswordAlgorithmSpec iteratedAlgorithmSpec = new IteratedSaltedPasswordAlgorithmSpec(iterationCount,
                salt);
        EncryptablePasswordSpec encryptableSpec = new EncryptablePasswordSpec(password.toCharArray(), iteratedAlgorithmSpec);

View on GitHub (pinned to e1c734241f)

Solutions

  1. Pass a positive iteration count; the Elytron default is 10 (use BcryptUtil.bcryptHash(password) for the default).
  2. If reading iteration count from config, guard with a fallback default when <= 0.
  3. Ensure no variable-shadowing bug passes the salt length or another int into the iterationCount parameter.

Example fix

// before
int rounds = config.bcryptRounds(); // 0 when unset
String hash = BcryptUtil.bcryptHash(pwd, rounds, salt);
// after
int rounds = Math.max(config.bcryptRounds(), 10);
String hash = BcryptUtil.bcryptHash(pwd, rounds, salt);
Defensive patterns

Strategy: validation

Validate before calling

// validate iteration count before calling bcryptHash
if (iterationCount <= 0) {
    iterationCount = 10; // Elytron default
}
String hash = BcryptUtil.bcryptHash(password, iterationCount, salt);

Prevention

When it happens

Trigger: Calling bcryptHash with an iteration count <= 0 — typically a variable holding a config value of 0/default, a failed Integer.parseInt yielding bad data, or code passing a sentinel -1 for 'default'.

Common situations: quarkus.security.users.embedded.bcrypt iteration count property set to 0 or left unset and read as 0; programmatic hashing in tests with an uninitialized counter; copying the 3-arg overload and passing salt iteration count by mistake.

Understand the failure class

Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.

Related errors


AI-assisted analysis of quarkusio/quarkus@e1c734241f (2026-09-05). Data as JSON: /api/errors/6c4cb9d24b01bf2c. Report an issue: GitHub.