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

  1. Use a 12-byte (96-bit) IV for AES-GCM: SecureRandom-generated byte[12].
  2. Let the library generate the IV itself instead of supplying one.
  3. Ensure tag buffers are the full algorithm tag size (e.g. 128 bits for GCM default).
  4. 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

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


AI-assisted analysis of jwtk/jjwt@fb71496164 (2026-09-09). Data as JSON: /api/errors/8f626da96c7fae4e. Report an issue: GitHub.