apache/dubbo · error · IndexOutOfBoundsException

hex2bytes: offset < 0, offset is {}

Error message

hex2bytes: offset < 0, offset is {}

What it means

Thrown by Bytes.hex2bytes(String, int, int) when the offset argument is negative. This is the index bounds check for the source string region, running after the even-length check. offset must be within [0, str.length()] so the substring region is valid.

Source

Thrown at dubbo-common/src/main/java/org/apache/dubbo/common/io/Bytes.java:443

    public static byte[] hex2bytes(String str) {
        return hex2bytes(str, 0, str.length());
    }

    /**
     * from hex string.
     *
     * @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.

View on GitHub (pinned to 3a3043227f)

Solutions

  1. Validate offset >= 0 before calling hex2bytes.
  2. Use hex2bytes(String) for the whole string to avoid manual offset.
  3. Range-check parsed offsets against the string length at the parsing boundary.

Example fix

// before
int off = indexOfHex - 1; // negative if indexOfHex == 0
byte[] b = Bytes.hex2bytes(hex, off, len); // throws [155]

// after
if (off < 0 || off + len > hex.length()) throw new IllegalArgumentException();
byte[] b = Bytes.hex2bytes(hex, off, len);
Defensive patterns

Strategy: validation

Validate before calling

if (off < 0) throw new IllegalArgumentException("negative offset: " + off);
byte[] b = Bytes.hex2bytes(str, off, len);

Prevention

When it happens

Trigger: Calling Bytes.hex2bytes(str, off, len) with off < 0. Typically from a parsed/decoded offset that was not range-checked, or a sentinel -1 value.

Common situations: Offset computed from a binary field that yielded -1 as 'not found'; index math underflow; passing a cursor that was decremented below zero.

Related errors


AI-assisted analysis of apache/dubbo@3a3043227f (2026-08-14). Data as JSON: /api/errors/0673a7fb3f87ae89. Report an issue: GitHub.