jwtk/jjwt · error · IllegalArgumentException

Byte array must be exactly ${bitsMsg(this.bitLength)}. Found

Error message

Byte array must be exactly ${bitsMsg(this.bitLength)}. Found ${bitsMsg(len)}

What it means

RequiredBitLengthConverter.assertLength enforces that a byte array has an exact bit length when the converter was created with exact=true. If Bytes.bitLength(bytes) differs from the configured bitLength, this IllegalArgumentException reports the required and found sizes (via Bytes.bitsMsg).

Source

Thrown at impl/src/main/java/io/jsonwebtoken/impl/lang/RequiredBitLengthConverter.java:41

    private final int bitLength;
    private final boolean exact;

    public RequiredBitLengthConverter(Converter<byte[], Object> converter, int bitLength) {
        this(converter, bitLength, true);
    }

    public RequiredBitLengthConverter(Converter<byte[], Object> converter, int bitLength, boolean exact) {
        this.converter = Assert.notNull(converter, "Converter cannot be null.");
        this.bitLength = Assert.gt(bitLength, 0, "bitLength must be greater than 0");
        this.exact = exact;
    }

    private byte[] assertLength(byte[] bytes) {
        long len = Bytes.bitLength(bytes);
        if (exact && len != this.bitLength) {
            String msg = "Byte array must be exactly " + Bytes.bitsMsg(this.bitLength) + ". Found " + Bytes.bitsMsg(len);
            throw new IllegalArgumentException(msg);
        } else if (len < this.bitLength) {
            String msg = "Byte array must be at least " + Bytes.bitsMsg(this.bitLength) + ". Found " + Bytes.bitsMsg(len);
            throw new IllegalArgumentException(msg);
        }
        return bytes;
    }

    @Override
    public Object applyTo(byte[] bytes) {
        assertLength(bytes);
        return this.converter.applyTo(bytes);
    }

    @Override
    public byte[] applyFrom(Object o) {
        byte[] result = this.converter.applyFrom(o);
        return assertLength(result);
    }

View on GitHub (pinned to fb71496164)

Solutions

  1. Generate or resize the byte array to the exact required length (e.g. 16 bytes for 128 bits).
  2. Use Keys.secretKeyFor(SignatureAlgorithm) or a proper key generator instead of hand-built arrays.
  3. Verify with bytes.length * 8 == requiredBits before calling the API.

Example fix

// before
byte[] key = new byte[15]; // 120 bits
// after
byte[] key = new byte[16]; // exactly 128 bits
Defensive patterns

Strategy: validation

Validate before calling

void requireExactBits(byte[] b, long bits) {
    long len = b.length * 8L; // approximate; matches Bytes.bitLength semantics
    if (len != bits) throw new IllegalArgumentException("Need exactly " + bits + " bits, got " + len);
}

Try / catch

try {
    converter.applyTo(bytes);
} catch (IllegalArgumentException e) {
    if (e.getMessage() != null && e.getMessage().startsWith("Byte array must be exactly")) {
        // regenerate/resize the byte array
    }
    throw e;
}

Prevention

When it happens

Trigger: Providing a key/byte-array parameter (e.g. a 128-bit key claim) whose length in bits is not exactly the required amount, such as a 120-bit array where 128 bits is exact-required.

Common situations: Manually generated keys of the wrong size; keys trimmed or padded by other tooling; base64url-decoding inputs that lost bytes.

Understand the failure class

Background: "value must be between 0 and 1" / "out of range" / "must not be negative" errors: fixing range-validation failures across open-source libraries — this error's family across 42 libraries.

Related errors


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