{"record":{"id":"ee5184353da6f73d","repo":"chinabugotech/hutool","slug":"position-is-out-of-maxlength","errorCode":null,"errorMessage":"Position is out of maxLength: {}","messagePattern":"Position is out of maxLength: (.+?)","errorType":"exception","errorClass":"IndexOutOfBoundsException","httpStatus":null,"severity":"error","filePath":"hutool-core/src/main/java/cn/hutool/core/io/BufferUtil.java","lineNumber":182,"sourceCode":"\t\tboolean canEnd = false;\n\t\tint charIndex = primitivePosition;\n\t\tbyte b;\n\t\twhile (buffer.hasRemaining()) {\n\t\t\tb = buffer.get();\n\t\t\tcharIndex++;\n\t\t\tif (b == StrUtil.C_CR) {\n\t\t\t\tcanEnd = true;\n\t\t\t} else if (b == StrUtil.C_LF) {\n\t\t\t\treturn canEnd ? charIndex - 2 : charIndex - 1;\n\t\t\t} else {\n\t\t\t\t// 只有\\r无法确认换行\n\t\t\t\tcanEnd = false;\n\t\t\t}\n\n\t\t\tif (charIndex - primitivePosition > maxLength) {\n\t\t\t\t// 查找到尽头，未找到，还原位置\n\t\t\t\tbuffer.position(primitivePosition);\n\t\t\t\tthrow new IndexOutOfBoundsException(StrUtil.format(\"Position is out of maxLength: {}\", maxLength));\n\t\t\t}\n\t\t}\n\n\t\t// 查找到buffer尽头，未找到，还原位置\n\t\tbuffer.position(primitivePosition);\n\t\t// 读到结束位置\n\t\treturn -1;\n\t}\n\n\t/**\n\t * 读取一行，如果buffer中最后一部分并非完整一行，则返回null<br>\n\t * 支持的换行符如下：\n\t *\n\t * <pre>\n\t * 1. \\r\\n\n\t * 2. \\n\n\t * </pre>\n\t *","sourceCodeStart":164,"sourceCodeEnd":200,"githubUrl":"https://github.com/chinabugotech/hutool/blob/8870454b2a0c29cc6ffd31dcf5667c8ceb2fc442/hutool-core/src/main/java/cn/hutool/core/io/BufferUtil.java#L164-L200","documentation":"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.","triggerScenarios":"Calling BufferUtil.lineEnd(buffer, maxLength) when the data from the current position to the next newline (or end of buffer) exceeds maxLength bytes.","commonSituations":"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.","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."],"exampleFix":"// before: throws when a line exceeds 1024 bytes\nint end = BufferUtil.lineEnd(buf, 1024);\n\n// after: scan the whole remaining buffer, no bound error\nint end = BufferUtil.lineEnd(buf);\n// or size the bound to real data\nint end = BufferUtil.lineEnd(buf, buf.remaining());","handlingStrategy":"validation","validationCode":"int remaining = buffer.remaining();\n// if you cannot guarantee a line fits, scan the whole buffer instead:\nint end = BufferUtil.lineEnd(buffer); // returns -1 instead of throwing\n// or size the bound to the data:\n// int end = BufferUtil.lineEnd(buffer, remaining);","typeGuard":null,"tryCatchPattern":"try {\n    int end = BufferUtil.lineEnd(buf, maxLength);\n} catch (IndexOutOfBoundsException e) {\n    // no newline within maxLength: buf position was reset; treat as one long line or expand bound\n}","preventionTips":["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."],"tags":["io","nio","bytebuffer","bounds"],"backgroundTag":null,"analyzedSha":"8870454b2a0c29cc6ffd31dcf5667c8ceb2fc442","analyzedAt":"2026-08-14T04:01:12.892Z","schemaVersion":2},"datasetVersion":"2026-08-14T05:17:29.042Z"}