TooTallNate/Java-WebSocket · error · IllegalArgumentException
Cannot have offset of
Error message
Cannot have offset of %d and length of %d with array of length %d
What it means
encodeBytesToBytes verifies that the requested slice off+len fits within the source array. When it would read past the end, the library throws IllegalArgumentException with the offending offset, length, and array length. It protects against out-of-bounds reads that would otherwise throw ArrayIndexOutOfBoundsException deeper in the encoder.
Solutions
- Clamp the slice: len = Math.min(len, source.length - off) before encoding.
- Assert off >= 0 && off + len <= source.length before the call.
- If the length comes from external data, validate it against source.length at the deserialization boundary.
Example fix
// before
byte[] out = Base64.encodeBytesToBytes(data, off, len);
// after
if (off < 0 || len < 0 || off + len > data.length) {
throw new IllegalArgumentException("slice out of bounds");
}
byte[] out = Base64.encodeBytesToBytes(data, off, len); Defensive patterns
Strategy: validation
Validate before calling
if (data != null && off >= 0 && len >= 0 && off + len <= data.length) {
byte[] out = Base64.encodeBytesToBytes(data, off, len);
} Type guard
static boolean inBounds(byte[] a, int off, int len) {
return a != null && off >= 0 && len >= 0 && off <= a.length && len <= a.length - off;
} Try / catch
try {
out = Base64.encodeBytesToBytes(data, off, len);
} catch (IllegalArgumentException e) {
logger.warn("encode slice out of bounds: " + e.getMessage());
out = EMPTY;
} Prevention
- Clamp with len = Math.min(len, data.length - off).
- Re-derive lengths from the current array, never cache them across buffer resizes.
- Watch for off-by-one: length is count of bytes, not an end index.
When it happens
Trigger: Calling encodeBytesToBytes(source, off, len) where off + len > source.length, e.g. passing a length measured in a different unit (chars vs bytes) or reusing a length from another array.
Common situations: Copying a cached length from a previous larger buffer; off-by-one when the length was meant to be source.length - off; encoding a subrange after the array was reallocated smaller.
Related errors
- Cannot have length offset:
- Source array was null.
- Destination array was null.
- Source array with length
- Destination array with length
AI-assisted analysis of TooTallNate/Java-WebSocket@afeacbf8c0 (2026-09-09).
Data as JSON: /api/errors/84671735e5fe9f28.
Report an issue: GitHub.
Appendix: source
Thrown at src/main/java/org/java_websocket/util/Base64.java:664
* @since 2.3.1
*/
public static byte[] encodeBytesToBytes(byte[] source, int off, int len, int options)
throws java.io.IOException {
if (source == null) {
throw new IllegalArgumentException("Cannot serialize a null array.");
} // end if: null
if (off < 0) {
throw new IllegalArgumentException("Cannot have negative offset: " + off);
} // end if: off < 0
if (len < 0) {
throw new IllegalArgumentException("Cannot have length offset: " + len);
} // end if: len < 0
if (off + len > source.length) {
throw new IllegalArgumentException(
String
.format("Cannot have offset of %d and length of %d with array of length %d", off, len,
source.length));
} // end if: off < 0
// Compress?
if ((options & GZIP) != 0) {
java.io.ByteArrayOutputStream baos = null;
java.util.zip.GZIPOutputStream gzos = null;
Base64.OutputStream b64os = null;
try {
// GZip -> Base64 -> ByteArray
baos = new java.io.ByteArrayOutputStream();
b64os = new Base64.OutputStream(baos, ENCODE | options);
gzos = new java.util.zip.GZIPOutputStream(b64os);
gzos.write(source, off, len);View on GitHub (pinned to afeacbf8c0)