jwtk/jjwt · error · IllegalArgumentException
The '${id}' algorithm requires ${type} with a length of ${bi
Error message
The '${id}' algorithm requires ${type} with a length of ${bitsMsg(requiredLengthInBits)}. The provided key has a length of ${bitsMsg(bitLen)}. What it means
IllegalArgumentException from AesAlgorithm.assertBytes when an input byte array (typically an IV/nonce or GCM tag) does not exactly equal the required bit length, as opposed to keys which only need a minimum. The exact match requirement comes from the JWA spec (e.g. 96-bit GCM IVs).
Source
Thrown at impl/src/main/java/io/jsonwebtoken/impl/security/AesAlgorithm.java:138
if (propagate) {
throw re;
}
//can't get the bytes to validate, e.g. hardware security module or later Android, so just return:
return null;
}
long keyBitLength = Bytes.bitLength(keyBytes);
if (keyBitLength < requiredBitLength) {
throw new WeakKeyException(lengthMsg(getId(), "keys", requiredBitLength, keyBitLength));
}
return keyBytes;
}
protected byte[] assertBytes(byte[] bytes, String type, int requiredBitLen) {
long bitLen = Bytes.bitLength(bytes);
if (requiredBitLen != bitLen) {
String msg = lengthMsg(getId(), type, requiredBitLen, bitLen);
throw new IllegalArgumentException(msg);
}
return bytes;
}
byte[] assertIvLength(final byte[] iv) {
return assertBytes(iv, "initialization vectors", this.ivBitLength);
}
byte[] assertTag(byte[] tag) {
return assertBytes(tag, "authentication tags", this.tagBitLength);
}
byte[] assertDecryptionIv(IvSupplier src) throws IllegalArgumentException {
byte[] iv = src.getIv();
Assert.notEmpty(iv, DECRYPT_NO_IV);
return assertIvLength(iv);
}
View on GitHub (pinned to fb71496164)
Solutions
- Use a 12-byte (96-bit) IV for AES-GCM: SecureRandom-generated byte[12].
- Let the library generate the IV itself instead of supplying one.
- Ensure tag buffers are the full algorithm tag size (e.g. 128 bits for GCM default).
- If using CBC-style algorithms, confirm required IV bit length matches the block size (128 bits).
Example fix
// before byte[] iv = new byte[16]; // 128-bit IV byte[] tag = ...; alg.encrypt(new SecureRequest<>(plaintext, key).setIv(iv)); // after byte[] iv = new byte[12]; // 96-bit GCM IV new SecureRandom().nextBytes(iv); alg.encrypt(new SecureRequest<>(plaintext, key).setIv(iv));
Defensive patterns
Strategy: validation
Validate before calling
static byte[] newGcmIv() {
byte[] iv = new byte[12]; // 96 bits
new SecureRandom().nextBytes(iv);
return iv;
}
assert iv.length * 8 == 96 : "GCM IV must be 96 bits"; Try / catch
try {
alg.encrypt(req.iv(iv));
} catch (IllegalArgumentException e) {
if (e.getMessage().contains("initialization vectors")) {
req.iv(newGcmIv()); // regenerate correct-size IV
} else throw e;
} Prevention
- Use 12-byte IVs for AES-GCM, 16-byte for AES-CBC - know your algorithm
- Prefer letting jjwt generate IVs instead of supplying your own
- Never reuse a GCM IV with the same key
- Keep a constant IV_LENGTH per algorithm in your crypto utility class
When it happens
Trigger: Supplying a custom IV of non-96-bit length to a GCM algorithm via a custom AesAlgorithm instance or Asserting a tag buffer whose size differs from the algorithm's tagBitLength; usually only hit when extending/using low-level algorithm APIs.
Common situations: Hand-rolling an AES-GCM IV that is 16 bytes (128 bits) instead of 12 bytes (96 bits); truncating or padding a tag during custom decryption; reusing code written for CBC (16-byte IV) with GCM.
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
- Unexpected content JWE.
- Unexpected Claims JWE.
- The '${id}' algorithm requires keys with a length of ${bitsM
- derivedKeyBitLength may not exceed ${bitsMsg(MAX_DERIVED_KEY
- Invalid RSA key algorithm name.
AI-assisted analysis of jwtk/jjwt@fb71496164 (2026-09-09).
Data as JSON: /api/errors/8f626da96c7fae4e.
Report an issue: GitHub.