jwtk/jjwt · error · IllegalArgumentException
numBytes argument must be >= 0
Error message
numBytes argument must be >= 0
What it means
Bytes.random(numBytes) generates a secure random byte array of the requested size and rejects numBytes <= 0 with an IllegalArgumentException. Note the message says >= 0 while the check is numBytes <= 0, so effectively only strictly positive sizes are allowed. It is normally reached indirectly via Bytes.randomBits(numBits).
Source
Thrown at impl/src/main/java/io/jsonwebtoken/impl/lang/Bytes.java:45
private static final int INT_BYTE_LENGTH = Integer.SIZE / Byte.SIZE;
public static final String LONG_REQD_MSG = "Long byte arrays must be " + LONG_BYTE_LENGTH + " bytes in length.";
public static final String INT_REQD_MSG = "Integer byte arrays must be " + INT_BYTE_LENGTH + " bytes in length.";
//prevent instantiation
private Bytes() {
}
public static byte[] nullSafe(byte[] bytes) {
return bytes != null ? bytes : Bytes.EMPTY;
}
public static byte[] randomBits(int numBits) {
return random(numBits / Byte.SIZE);
}
public static byte[] random(int numBytes) {
if (numBytes <= 0) {
throw new IllegalArgumentException("numBytes argument must be >= 0");
}
byte[] bytes = new byte[numBytes];
Randoms.secureRandom().nextBytes(bytes);
return bytes;
}
public static byte[] toBytes(int i) {
return new byte[]{
(byte) (i >>> 24),
(byte) (i >>> 16),
(byte) (i >>> 8),
(byte) i
};
}
public static byte[] toBytes(long l) {
return new byte[]{
(byte) (l >>> 56),View on GitHub (pinned to fb71496164)
Solutions
- Pass at least 1 byte: Bytes.random(16) for a 128-bit value, etc.
- For randomBits, request at least 8 bits (or round up: (numBits + 7) / 8).
- Validate configured sizes (from properties/env) are > 0 before calling.
Example fix
// before byte[] iv = Bytes.randomBits(config.getIvBits()); // 0 bits -> crash // after int bits = Math.max(config.getIvBits(), 128); byte[] iv = Bytes.random((bits + 7) / Byte.SIZE);
Defensive patterns
Strategy: validation
Validate before calling
if (numBytes <= 0) {
throw new IllegalArgumentException("need at least 1 random byte, got " + numBytes);
}
byte[] bytes = Bytes.random(numBytes); Try / catch
try {
byte[] bytes = Bytes.random(n);
} catch (IllegalArgumentException e) {
bytes = Bytes.random(16); // sensible default
} Prevention
- Define random sizes as positive constants (16/24/32 bytes)
- Remember randomBits truncates: request at least 8 bits
- Validate size-bearing config values at startup
When it happens
Trigger: Calling Bytes.random(0) or Bytes.random(negativeInt), or Bytes.randomBits with numBits in [0, 7] since numBits / 8 truncates to 0.
Common situations: Generating an IV/nonce/salt with a size computed from configuration that resolved to 0; requesting fewer than 8 random bits via randomBits; integer division silently truncating a bit-length below one byte.
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
- bitLength argument must be >= 0
- constant [%s] does not exist in enum type %s
- Values must be either String or ${type.getName()} instances.
- bitLength must be an even multiple of 8
AI-assisted analysis of jwtk/jjwt@fb71496164 (2026-09-09).
Data as JSON: /api/errors/2467d2b1f996d471.
Report an issue: GitHub.