apache/cassandra · error · ConfigurationException

Bad value for system property -D%s.Please use a value betwee

Error message

Bad value for system property -D%s.Please use a value between 4 and 30 inclusively

What it means

PasswordSaltSupplier reads the system property cassandra.auth_bcrypt_gensalt_log2_rounds to control bcrypt cost. getGensaltLogRounds() validates the value and throws ConfigurationException if it falls outside the supported 4-30 range, preventing startup with a cryptographically invalid or impractical cost factor.

Source

Thrown at src/java/org/apache/cassandra/auth/PasswordSaltSupplier.java:41

import com.google.common.annotations.VisibleForTesting;

import org.mindrot.jbcrypt.BCrypt;

import org.apache.cassandra.exceptions.ConfigurationException;

import static org.apache.cassandra.config.CassandraRelevantProperties.AUTH_BCRYPT_GENSALT_LOG2_ROUNDS;

public class PasswordSaltSupplier
{
    // 2 ** GENSALT_LOG2_ROUNDS rounds of hashing will be performed.
    private static final int GENSALT_LOG2_ROUNDS = getGensaltLogRounds();

    @VisibleForTesting
    static int getGensaltLogRounds()
    {
        int rounds = AUTH_BCRYPT_GENSALT_LOG2_ROUNDS.getInt();
        if (rounds < 4 || rounds > 30)
            throw new ConfigurationException(String.format("Bad value for system property -D%s." +
                                                           "Please use a value between 4 and 30 inclusively",
                                                           AUTH_BCRYPT_GENSALT_LOG2_ROUNDS.getKey()));
        return rounds;
    }
    private static Supplier<String> DEFAULT_SALT_SUPPLIER = () -> BCrypt.gensalt(GENSALT_LOG2_ROUNDS);
    private static Supplier<String> saltSupplier = DEFAULT_SALT_SUPPLIER;

    public static void unsafeSet(Supplier<String> newSaltSupplier)
    {
        assert newSaltSupplier != null;
        saltSupplier = newSaltSupplier;
    }
    public static void unsafeReset()
    {
        saltSupplier = DEFAULT_SALT_SUPPLIER;
    }

    public static String get()

View on GitHub (pinned to 88fd0f6a0e)

Solutions

  1. Set the property to an integer between 4 and 30 inclusive (10-12 is typical)
  2. Remove the -D flag entirely to use the default bcrypt cost
  3. Fix the value in the startup script/systemd unit/cassandra-env.sh where it is defined

Example fix

// before
JVM_OPTS="$JVM_OPTS -Dcassandra.auth_bcrypt_gensalt_log2_rounds=50"
// after
JVM_OPTS="$JVM_OPTS -Dcassandra.auth_bcrypt_gensalt_log2_rounds=12"
Defensive patterns

Strategy: validation

Validate before calling

int v = Integer.parseInt(System.getProperty("cassandra.auth_bcrypt_gensalt_log2_rounds", "10")); if (v < 4 || v > 30) fail("bcrypt rounds must be 4-30");

Type guard

boolean isValidGensaltRounds(String v) { try { int n = Integer.parseInt(v); return n >= 4 && n <= 30; } catch (NumberFormatException e) { return false; } }

Try / catch

try { startWith(opts); } catch (ConfigurationException e) { if (e.getMessage().contains("4 and 30")) fallbackToDefaultRounds(); }

Prevention

When it happens

Trigger: Passing -Dcassandra.auth_bcrypt_gensalt_log2_rounds=<int> outside 4..30 (e.g. 2, 0, 50, negative) at JVM startup; a typo producing a non-parseable-then-clamped or extreme value.

Common situations: Operators tuning bcrypt cost for performance/security and overshooting the allowed range; copied startup scripts with aggressive low values; guessing the range instead of reading docs.

Understand the failure class

Background: "is not a valid" / "Invalid ... value" environment variable errors: how libraries validate env vars and what to do when they reject yours — this error's family across 48 libraries.

Related errors


AI-assisted analysis of apache/cassandra@88fd0f6a0e (2026-09-10). Data as JSON: /api/errors/e51639a67d93bcc8. Report an issue: GitHub.