apache/dubbo · error · IndexOutOfBoundsException
hex2bytes: offset + length > array length.
Error message
hex2bytes: offset + length > array length.
What it means
Thrown by Bytes.hex2bytes(String, int, int) when off + len exceeds the source string length. This upper-bound check ensures the requested character region [off, off+len) lies within the string, preventing StringIndexOutOfBoundsException during charAt reads in the conversion loop. It is the last of the four hex2bytes validations.
Source
Thrown at dubbo-common/src/main/java/org/apache/dubbo/common/io/Bytes.java:449
*
* @param str hex string.
* @param off offset.
* @param len length.
* @return byte array.
*/
public static byte[] hex2bytes(final String str, final int off, int len) {
if ((len & 1) == 1) {
throw new IllegalArgumentException("hex2bytes: ( len & 1 ) == 1.");
}
if (off < 0) {
throw new IndexOutOfBoundsException("hex2bytes: offset < 0, offset is " + off);
}
if (len < 0) {
throw new IndexOutOfBoundsException("hex2bytes: length < 0, length is " + len);
}
if (off + len > str.length()) {
throw new IndexOutOfBoundsException("hex2bytes: offset + length > array length.");
}
int num = len / 2, r = off, w = 0;
byte[] b = new byte[num];
for (int i = 0; i < num; i++) {
b[w++] = (byte) (hex(str.charAt(r++)) << 4 | hex(str.charAt(r++)));
}
return b;
}
/**
* to base64 string.
*
* @param b byte array.
* @return base64 string.
*/
public static String bytes2base64(byte[] b) {
return bytes2base64(b, 0, b.length, BASE64);View on GitHub (pinned to 3a3043227f)
Solutions
- Recompute len against the actual string length: len = Math.min(len, str.length() - off).
- Use hex2bytes(String) for the whole string.
- Ensure the string and its computed region are derived from the same source.
Example fix
// before String hex = fullHex.substring(0, 10); byte[] b = Bytes.hex2bytes(hex, 0, fullHex.length()); // throws [157] // after byte[] b = Bytes.hex2bytes(hex, 0, hex.length());
Defensive patterns
Strategy: validation
Validate before calling
if (off + len > str.length()) len = str.length() - off; // clamp byte[] b = Bytes.hex2bytes(str, off, len);
Prevention
- Recompute len against the actual string length after truncation.
- Use hex2bytes(String) for the whole string.
- Ensure the string and its region come from the same source.
When it happens
Trigger: Calling Bytes.hex2bytes(str, off, len) where off + len > str.length(). Usually a stale length computed against a longer string, or a substring that was trimmed but the old length retained.
Common situations: Truncating a hex string but keeping the original length; off-by-one including the null terminator or delimiter in len; concatenation/removal that changed string size after length was computed.
Related errors
- bytes2hex: offset < 0, offset is {}
- bytes2hex: length < 0, length is {}
- bytes2hex: offset + length > array length.
- hex2bytes: offset < 0, offset is {}
- hex2bytes: length < 0, length is {}
AI-assisted analysis of apache/dubbo@3a3043227f (2026-08-14).
Data as JSON: /api/errors/3315257157e9355c.
Report an issue: GitHub.