TooTallNate/Java-WebSocket · error · IllegalArgumentException

Cannot have negative offset:

Error message

Cannot have negative offset: 

What it means

Base64.encodeBytesToBytes validates the offset/length window into the source array: a negative off throws IllegalArgumentException("Cannot have negative offset: N") and a negative len throws for length. Together with bounds checks these guards ensure only a valid slice of the array is encoded.

Solutions

  1. Validate off >= 0 && len >= 0 (and off + len <= source.length) before calling; clamp or reject invalid windows.
  2. Fix the computation producing the negative value — check for -1 sentinel returns from searches/reads and handle them before encoding.
  3. If encoding whole arrays, use the no-offset overload encodeBytesToBytes(source) so off=0/len=source.length are applied automatically.

Example fix

// before
int off = input.indexOf(marker); // may be -1
byte[] out = Base64.encodeBytesToBytes(data, off, data.length - off, Base64.NO_OPTIONS);
// after
int off = input.indexOf(marker);
if (off >= 0 && data.length - off >= 0) {
  byte[] out = Base64.encodeBytesToBytes(data, off, data.length - off, Base64.NO_OPTIONS);
}
Defensive patterns

Strategy: validation

Validate before calling

if (off < 0 || len < 0 || off + len > source.length) {
  throw new IllegalArgumentException(
      "Invalid window: off=" + off + " len=" + len + " size=" + source.length);
}

Type guard

static boolean validWindow(byte[] src, int off, int len) {
  return src != null && off >= 0 && len >= 0 && off <= src.length && len <= src.length - off;
}

Try / catch

try {
  byte[] out = Base64.encodeBytesToBytes(source, off, len, options);
} catch (IllegalArgumentException e) {
  log.warn("Invalid encode window: {}", e.getMessage());
  out = null;
}

Prevention

When it happens

Trigger: Calling encodeBytesToBytes(source, off, len, options) with a negative off or len — typically computed values (positions, chunk sizes) that went negative, or swapped arguments where len was passed in the off position.

Common situations: Chunked encoding loops where chunk start/size arithmetic underflows; passing -1 as a 'default' length; wrapping native/parsed lengths that failed and returned -1 sentinel values.

Related errors


AI-assisted analysis of TooTallNate/Java-WebSocket@afeacbf8c0 (2026-09-09). Data as JSON: /api/errors/47c51cb58ebcfbc6. Report an issue: GitHub.

Appendix: source

Thrown at src/main/java/org/java_websocket/util/Base64.java:656

   * @param len     Length of data to convert
   * @param options Specified options
   * @return The Base64-encoded data as a String
   * @throws java.io.IOException      if there is an error
   * @throws IllegalArgumentException if source array is null, if source array, offset, or length
   *                                  are invalid
   * @see Base64#GZIP
   * @see Base64#DO_BREAK_LINES
   * @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;

View on GitHub (pinned to afeacbf8c0)