apache/pulsar · error · IndexOutOfBoundsException
off=${off}, len=${len}, b.length=${b.length}
Error message
off=${off}, len=${len}, b.length=${b.length} What it means
BlockAwareSegmentInputStreamImpl.read(byte[], int, int) enforces InputStream argument bounds: if off < 0, len < 0, or len > b.length - off, it throws IndexOutOfBoundsException with the offending off/len/b.length values.
Source
Thrown at tiered-storage/jcloud/src/main/java/org/apache/bookkeeper/mledger/offload/jcloud/impl/BlockAwareSegmentInputStreamImpl.java:223
entries.add(entryBuf);
}
return entries;
} catch (InterruptedException | ExecutionException e) {
log.error().exception(e).log("Exception when getting LedgerEntries");
if (e instanceof InterruptedException) {
Thread.currentThread().interrupt();
}
throw new IOException(e);
}
}
@Override
public int read(byte[] b, int off, int len) throws IOException {
if (b == null) {
throw new NullPointerException("The given bytes are null");
} else if (off < 0 || len < 0 || len > b.length - off) {
throw new IndexOutOfBoundsException("off=" + off + ", len=" + len + ", b.length=" + b.length);
} else if (len == 0) {
return 0;
}
int offset = off;
int readLen = len;
int readBytes = 0;
// reading header
if (dataBlockHeaderStream.available() > 0) {
int read = dataBlockHeaderStream.read(b, off, len);
offset += read;
readLen -= read;
readBytes += read;
bytesReadOffset += read;
}
if (readLen == 0) {
return readBytes;
}View on GitHub (pinned to 820761864e)
Solutions
- Validate before calling: ensure 0 <= off <= b.length and 0 <= len <= b.length - off
- Clamp len to Math.min(len, b.length - off) and bail out when it becomes <= 0
- Check block-size/off calculations in the offload copy loop
Example fix
// before int n = stream.read(buf, off, buf.length); // IOOBE when off > 0 // after int len = Math.min(requested, buf.length - off); int n = len > 0 ? stream.read(buf, off, len) : -1;
Defensive patterns
Strategy: validation
Validate before calling
static int[] validated(byte[] b, int off, int len) {
if (off < 0 || len < 0 || len > b.length - off)
throw new IndexOutOfBoundsException("off=" + off + ", len=" + len + ", b.length=" + b.length);
return new int[]{off, len};
} Type guard
static boolean inBounds(byte[] b, int off, int len) {
return b != null && off >= 0 && len >= 0 && len <= b.length - off;
} Try / catch
try {
int n = stream.read(buf, off, len);
} catch (IndexOutOfBoundsException e) {
if (e.getMessage() != null && e.getMessage().startsWith("off=")) {
off = 0; len = Math.min(len, buf.length); // recompute and retry
} else throw e;
} Prevention
- Clamp len to b.length - off before every read
- Recompute remaining bytes after partial reads instead of reusing stale off/len
- Prefer helper wrappers (e.g. DataInputStream.readFully semantics) that handle bounds
When it happens
Trigger: Calling read(b, off, len) where off+len exceeds the buffer length, or off/len is negative — e.g. computing len from remaining bytes without clamping after EOF.
Common situations: Caller computing len = buffer.length - off with an off larger than the buffer; retry loops not shrinking len after partial reads; mismatched block-size constants between writer and reader.
Related errors
- The given bytes are null
- Cursor %s mark-delete position %s is ahead of the last posit
- Timeout during reset cursor
- Timeout during mark-delete operation
- Could not open configuration file
AI-assisted analysis of apache/pulsar@820761864e (2026-09-06).
Data as JSON: /api/errors/3c71ec61e00881c9.
Report an issue: GitHub.