jwtk/jjwt · error · IllegalArgumentException

bitLength argument must be >= 0

Error message

bitLength argument must be >= 0

What it means

Bytes.length(bitLength) computes the minimum number of bytes needed to represent a given number of bits and validates that the input is not negative, throwing IllegalArgumentException otherwise. It is a pure size utility used when sizing keys/byte arrays.

Source

Thrown at impl/src/main/java/io/jsonwebtoken/impl/lang/Bytes.java:224

     * Returns the minimum number of bytes required to represent the specified number of bits.
     *
     * <p>This is defined/used by many specifications, such as:</p>
     * <ul>
     *     <li><a href="https://www.rfc-editor.org/rfc/rfc7518.html#section-2">JWA RFC 7518, Section 2</a>'s
     *     <code>Base64urlUInt</code> definition</li>
     *     <li>Elliptic Curve <code>Integer-to-OctetString</code> conversion defined by Section 2.3.7 of the
     *     <a href="http://www.secg.org/sec1-v2.pdf">Standards for Efficient Cryptography Group,
     *     &qupt;SEC 1: Elliptic Curve Cryptography&quot; Version 2.0, May 2009</a> (as required by
     *     <a href="https://www.rfc-editor.org/rfc/rfc7518.html#section-3.4">RFC 7518, Section 3.4</a>)</li>
     *     <li>and others.</li>
     * </ul>
     *
     * @param bitLength the number of bits to represent as a byte array, must be >= 0
     * @return the minimum number of bytes required to represent the specified number of bits.
     * @throws IllegalArgumentException if {@code bitLength} is less than zero.
     */
    public static int length(int bitLength) {
        if (bitLength < 0) throw new IllegalArgumentException("bitLength argument must be >= 0");
        return (bitLength + 7) / Byte.SIZE;
    }

    public static String bitsMsg(long bitLength) {
        return bitLength + " bits (" + bitLength / Byte.SIZE + " bytes)";
    }

    public static String bytesMsg(int byteArrayLength) {
        return bitsMsg((long) byteArrayLength * Byte.SIZE);
    }

    public static void increment(byte[] a) {
        for (int i = a.length - 1; i >= 0; --i) {
            if (++a[i] != 0) {
                break;
            }
        }
    }

View on GitHub (pinned to fb71496164)

Solutions

  1. Clamp or validate before the call: if (bitLength < 0) throw/defaults.
  2. Fix the source of the negative number - usually an unset config value or a bad subtraction.
  3. Use a positive constant (e.g. 256 for a 256-bit key) instead of derived values where possible.

Example fix

// before
int bytes = Bytes.length(keyBits - overheadBits); // can go negative
// after
int bits = Math.max(keyBits - overheadBits, 0);
if (bits <= 0) throw new IllegalStateException("key size underflow");
int bytes = Bytes.length(bits);
Defensive patterns

Strategy: validation

Validate before calling

if (bitLength < 0) {
    throw new IllegalArgumentException("bitLength must be >= 0, got " + bitLength);
}
int bytes = Bytes.length(bitLength);

Try / catch

try {
    int len = Bytes.length(bits);
} catch (IllegalArgumentException e) {
    // log and use configured default key size
}

Prevention

When it happens

Trigger: Calling Bytes.length(negativeBitLength), typically when the bit length came from a misconfigured key size, a failed parse (Integer.parseInt of bad input producing unexpected math), or an arithmetic result that underflowed.

Common situations: Key-size configuration read as negative (e.g. '-1' default when unset); subtracting header overhead from a size and going below zero; computing bit length of an empty/missing value.

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/62aca667ae982d29. Report an issue: GitHub.