{"record":{"id":"2467d2b1f996d471","repo":"jwtk/jjwt","slug":"numbytes-argument-must-be-0","errorCode":null,"errorMessage":"numBytes argument must be >= 0","messagePattern":"numBytes argument must be >= 0","errorType":"validation","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"impl/src/main/java/io/jsonwebtoken/impl/lang/Bytes.java","lineNumber":45,"sourceCode":"    private static final int INT_BYTE_LENGTH = Integer.SIZE / Byte.SIZE;\n    public static final String LONG_REQD_MSG = \"Long byte arrays must be \" + LONG_BYTE_LENGTH + \" bytes in length.\";\n    public static final String INT_REQD_MSG = \"Integer byte arrays must be \" + INT_BYTE_LENGTH + \" bytes in length.\";\n\n    //prevent instantiation\n    private Bytes() {\n    }\n\n    public static byte[] nullSafe(byte[] bytes) {\n        return bytes != null ? bytes : Bytes.EMPTY;\n    }\n\n    public static byte[] randomBits(int numBits) {\n        return random(numBits / Byte.SIZE);\n    }\n\n    public static byte[] random(int numBytes) {\n        if (numBytes <= 0) {\n            throw new IllegalArgumentException(\"numBytes argument must be >= 0\");\n        }\n        byte[] bytes = new byte[numBytes];\n        Randoms.secureRandom().nextBytes(bytes);\n        return bytes;\n    }\n\n    public static byte[] toBytes(int i) {\n        return new byte[]{\n                (byte) (i >>> 24),\n                (byte) (i >>> 16),\n                (byte) (i >>> 8),\n                (byte) i\n        };\n    }\n\n    public static byte[] toBytes(long l) {\n        return new byte[]{\n                (byte) (l >>> 56),","sourceCodeStart":27,"sourceCodeEnd":63,"githubUrl":"https://github.com/jwtk/jjwt/blob/fb71496164c71442d08adec4571d9616ed5e1b8d/impl/src/main/java/io/jsonwebtoken/impl/lang/Bytes.java#L27-L63","documentation":"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).","triggerScenarios":"Calling Bytes.random(0) or Bytes.random(negativeInt), or Bytes.randomBits with numBits in [0, 7] since numBits / 8 truncates to 0.","commonSituations":"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.","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."],"exampleFix":"// before\nbyte[] iv = Bytes.randomBits(config.getIvBits()); // 0 bits -> crash\n// after\nint bits = Math.max(config.getIvBits(), 128);\nbyte[] iv = Bytes.random((bits + 7) / Byte.SIZE);","handlingStrategy":"validation","validationCode":"if (numBytes <= 0) {\n    throw new IllegalArgumentException(\"need at least 1 random byte, got \" + numBytes);\n}\nbyte[] bytes = Bytes.random(numBytes);","typeGuard":null,"tryCatchPattern":"try {\n    byte[] bytes = Bytes.random(n);\n} catch (IllegalArgumentException e) {\n    bytes = Bytes.random(16); // sensible default\n}","preventionTips":["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"],"tags":["random","bytes","argument-validation"],"backgroundTag":"invalid-argument-value","analyzedSha":"fb71496164c71442d08adec4571d9616ed5e1b8d","analyzedAt":"2026-09-09T00:33:09.982Z","contentChangedAt":"2026-09-09T00:33:09.982Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}