spring-projects/spring-security · error · IllegalArgumentException

Salt length must be >= 1 and <= {Integer.MAX_VALUE}

Error message

Salt length must be >= 1 and <= {Integer.MAX_VALUE}

What it means

The salt length must be at least 1 (and, per the message, within int range). SCryptPasswordEncoder builds a secure-random generator of exactly saltLength bytes; a saltLength < 1 would produce no salt, so the constructor throws IllegalArgumentException.

Source

Thrown at crypto/src/main/java/org/springframework/security/crypto/scrypt/SCryptPasswordEncoder.java:116

		if (cpuCost <= 1) {
			throw new IllegalArgumentException("Cpu cost parameter must be > 1.");
		}
		if (memoryCost == 1 && cpuCost > 65536) {
			throw new IllegalArgumentException("Cpu cost parameter must be > 1 and < 65536.");
		}
		if (memoryCost < 1) {
			throw new IllegalArgumentException("Memory cost must be >= 1.");
		}
		int maxParallel = Integer.MAX_VALUE / (128 * memoryCost * 8);
		if (parallelization < 1 || parallelization > maxParallel) {
			throw new IllegalArgumentException("Parallelisation parameter p must be >= 1 and <= " + maxParallel
					+ " (based on block size r of " + memoryCost + ")");
		}
		if (keyLength < 1 || keyLength > Integer.MAX_VALUE) {
			throw new IllegalArgumentException("Key length must be >= 1 and <= " + Integer.MAX_VALUE);
		}
		if (saltLength < 1 || saltLength > Integer.MAX_VALUE) {
			throw new IllegalArgumentException("Salt length must be >= 1 and <= " + Integer.MAX_VALUE);
		}
		this.cpuCost = cpuCost;
		this.memoryCost = memoryCost;
		this.parallelization = parallelization;
		this.keyLength = keyLength;
		this.saltGenerator = KeyGenerators.secureRandom(saltLength);
	}

	/**
	 * Constructs a SCrypt password encoder with cpu cost of 16,384, memory cost of 8,
	 * parallelization of 1, a key length of 32 and a salt length of 64 bytes.
	 * @return the {@link SCryptPasswordEncoder}
	 * @since 5.8
	 * @deprecated Use {@link #defaultsForSpringSecurity_v5_8()} instead
	 */
	@Deprecated
	public static SCryptPasswordEncoder defaultsForSpringSecurity_v4_1() {
		return new SCryptPasswordEncoder(16384, 8, 1, 32, 64);

View on GitHub (pinned to 96852e8860)

Solutions

  1. Pass a positive saltLength in bytes (e.g. 64, the library default).
  2. Check the config property is present and >= 1 before constructing.
  3. Use the no-arg SCryptPasswordEncoder() for default salt handling.

Example fix

// before
new SCryptPasswordEncoder(16384, 8, 1, 32, 0);
// after
new SCryptPasswordEncoder(16384, 8, 1, 32, 64);
Defensive patterns

Strategy: validation

Validate before calling

if (saltLength < 1) {
    throw new IllegalArgumentException("saltLength must be >= 1: " + saltLength);
}
new SCryptPasswordEncoder(cpuCost, memoryCost, p, keyLen, saltLength);

Try / catch

try {
    encoder = new SCryptPasswordEncoder(cpuCost, r, p, keyLen, saltLen);
} catch (IllegalArgumentException e) {
    encoder = new SCryptPasswordEncoder(); // default salt length 64
}

Prevention

When it happens

Trigger: `new SCryptPasswordEncoder(cpuCost, memoryCost, parallelization, keyLength, saltLength)` with saltLength < 1 (0 or negative).

Common situations: saltLength sourced from configuration defaulting to 0 when the property is missing; copying call sites and misordering the last two arguments; assuming 0 means 'use default'.

Related errors


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