apache/cassandra · error · IllegalArgumentException

A CQL blob string must have an even length (since one byte i

Error message

A CQL blob string must have an even length (since one byte is always 2 hexadecimal character)

What it means

Bytes.fromHexString converts a CQL blob literal string (0x-prefixed hex) into a ByteBuffer. Each byte requires exactly two hex characters, so an odd-length string cannot be a valid blob and this IllegalArgumentException is thrown before the prefix check. Note the odd-length check runs first, so an odd-length string reports this even if it also lacks '0x'.

Source

Thrown at src/java/org/apache/cassandra/cql3/functions/types/utils/Bytes.java:145

    {
        return toHexString(ByteBuffer.wrap(byteArray));
    }

    /**
     * Parse an hex string representing a CQL blob.
     *
     * <p>The input should be a valid representation of a CQL blob, i.e. it must start by "0x"
     * followed by the hexadecimal representation of the blob bytes.
     *
     * @param str the CQL blob string representation to parse.
     * @return the bytes corresponding to {@code str}. If {@code str} is {@code null}, this method
     * returns {@code null}.
     * @throws IllegalArgumentException if {@code str} is not a valid CQL blob string.
     */
    public static ByteBuffer fromHexString(String str)
    {
        if ((str.length() & 1) == 1)
            throw new IllegalArgumentException(
            "A CQL blob string must have an even length (since one byte is always 2 hexadecimal character)");

        if (str.charAt(0) != '0' || str.charAt(1) != 'x')
            throw new IllegalArgumentException("A CQL blob string must start with \"0x\"");

        return ByteBuffer.wrap(fromRawHexString(str, 2));
    }

    /**
     * Extract the content of the provided {@code ByteBuffer} as a byte array.
     *
     * <p>This method work with any type of {@code ByteBuffer} (direct and non-direct ones), but when
     * the {@code ByteBuffer} is backed by an array, this method will try to avoid copy when possible.
     * As a consequence, changes to the returned byte array may or may not reflect into the initial
     * {@code ByteBuffer}.
     *
     * @param bytes the buffer whose content to extract.
     * @return a byte array with the content of {@code bytes}. That array may be the array backing

View on GitHub (pinned to 88fd0f6a0e)

Solutions

  1. Pad the string to even length (typically prefix a single '0'): "0x0abc".
  2. Ensure the original value's full hex string is preserved end-to-end (avoid numeric parsing of hex strings).
  3. Validate even length after the '0x' prefix before calling.
  4. Generate blob strings with Bytes.toHexString(value) rather than hand-writing them.

Example fix

// before
ByteBuffer bb = Bytes.fromHexString("0xabc");
// after
ByteBuffer bb = Bytes.fromHexString("0x0abc"); // pad to even nibble count
Defensive patterns

Strategy: validation

Validate before calling

String s = str.trim(); String hex = s.startsWith("0x") ? s.substring(2) : s; if (hex.length() % 2 != 0) throw new IllegalArgumentException("odd hex length");

Try / catch

try { return Bytes.fromHexString(s); } catch (IllegalArgumentException e) { if (s.length() % 2 == 1) return Bytes.fromHexString("0x0" + s.replaceFirst("^0x", "")); throw e; }

Prevention

When it happens

Trigger: fromHexString("0xabc") (3 nibbles), fromHexString("abc") (odd length AND missing prefix), user input where a leading zero was stripped, manual string truncation.

Common situations: Display layers stripping leading zeros from hex values; hand-typed blob literals; clipboard/log truncation dropping the last hex char.

Understand the failure class

Background: "Invalid ... format", "must be in format X", "does not look like a ..." — invalid argument format errors across CLI tools and libraries — this error's family across 17 libraries.

Related errors


AI-assisted analysis of apache/cassandra@88fd0f6a0e (2026-09-10). Data as JSON: /api/errors/b68fb011ca49e6ce. Report an issue: GitHub.