chinabugotech/hutool · error · IndexOutOfBoundsException
Position is out of maxLength: {}
Error message
Position is out of maxLength: {} What it means
BufferUtil.lineEnd(buffer, maxLength) scans a ByteBuffer byte-by-byte for a CR/LF line terminator. If the scan travels more than maxLength bytes from the start position without finding a newline, it resets the buffer position and throws IndexOutOfBoundsException to prevent unbounded scanning.
Source
Thrown at hutool-core/src/main/java/cn/hutool/core/io/BufferUtil.java:182
boolean canEnd = false;
int charIndex = primitivePosition;
byte b;
while (buffer.hasRemaining()) {
b = buffer.get();
charIndex++;
if (b == StrUtil.C_CR) {
canEnd = true;
} else if (b == StrUtil.C_LF) {
return canEnd ? charIndex - 2 : charIndex - 1;
} else {
// 只有\r无法确认换行
canEnd = false;
}
if (charIndex - primitivePosition > maxLength) {
// 查找到尽头,未找到,还原位置
buffer.position(primitivePosition);
throw new IndexOutOfBoundsException(StrUtil.format("Position is out of maxLength: {}", maxLength));
}
}
// 查找到buffer尽头,未找到,还原位置
buffer.position(primitivePosition);
// 读到结束位置
return -1;
}
/**
* 读取一行,如果buffer中最后一部分并非完整一行,则返回null<br>
* 支持的换行符如下:
*
* <pre>
* 1. \r\n
* 2. \n
* </pre>
*View on GitHub (pinned to 8870454b2a)
Solutions
- Increase maxLength to at least the longest expected line length.
- Use the no-arg lineEnd(buffer) overload which defaults maxLength to buffer.remaining() and scans to buffer end (returns -1 instead of throwing).
- Pre-split or chunk input so individual line scans stay within the bound.
Example fix
// before: throws when a line exceeds 1024 bytes int end = BufferUtil.lineEnd(buf, 1024); // after: scan the whole remaining buffer, no bound error int end = BufferUtil.lineEnd(buf); // or size the bound to real data int end = BufferUtil.lineEnd(buf, buf.remaining());
Defensive patterns
Strategy: validation
Validate before calling
int remaining = buffer.remaining(); // if you cannot guarantee a line fits, scan the whole buffer instead: int end = BufferUtil.lineEnd(buffer); // returns -1 instead of throwing // or size the bound to the data: // int end = BufferUtil.lineEnd(buffer, remaining);
Try / catch
try {
int end = BufferUtil.lineEnd(buf, maxLength);
} catch (IndexOutOfBoundsException e) {
// no newline within maxLength: buf position was reset; treat as one long line or expand bound
} Prevention
- Size maxLength to the longest realistic line in your data.
- Prefer the no-arg lineEnd(buffer) when you do not have a hard per-line cap.
- Sanitize/line-split very long inputs (minified blobs, base64) before scanning.
When it happens
Trigger: Calling BufferUtil.lineEnd(buffer, maxLength) when the data from the current position to the next newline (or end of buffer) exceeds maxLength bytes.
Common situations: Processing minified JS/base64 blobs/log lines with very long lines using a maxLength that is too small; reading binary data containing no line terminators; reusing a small maxLength copied from a sample that didn't have long lines.
Related errors
- Destination Dir must be a Directory !
- Image type of file [{}] is not supported!
- Image type is not supported!
- Writer is closed!{}
- Not a regular file!
AI-assisted analysis of chinabugotech/hutool@8870454b2a (2026-08-14).
Data as JSON: /api/errors/ee5184353da6f73d.
Report an issue: GitHub.