TheAlgorithms/Python · error · ValueError

Base16 encoded data is invalid: Data does not have an even n

Error message

Base16 encoded data is invalid:
Data does not have an even number of hex digits.

What it means

Raised by base16_decode() when the input string has an odd number of characters. Per RFC 3548, each byte is exactly two hexadecimal digits, and the decoder builds bytes via int(data[i] + data[i+1], 16) in steps of 2 — an odd-length string would leave a dangling half-byte, so it is rejected before charset validation.

Source

Thrown at ciphers/base16.py:47

    Traceback (most recent call last):
      ...
    ValueError: Base16 encoded data is invalid:
    Data does not have an even number of hex digits.
    >>> base16_decode('48656c6c6f20576f726c6421')
    Traceback (most recent call last):
      ...
    ValueError: Base16 encoded data is invalid:
    Data is not uppercase hex or it contains invalid characters.
    >>> base16_decode('This is not base64 encoded data.')
    Traceback (most recent call last):
      ...
    ValueError: Base16 encoded data is invalid:
    Data is not uppercase hex or it contains invalid characters.
    """
    # Check data validity, following RFC3548
    # https://www.ietf.org/rfc/rfc3548.txt
    if (len(data) % 2) != 0:
        raise ValueError(
            """Base16 encoded data is invalid:
Data does not have an even number of hex digits."""
        )
    # Check the character set - the standard base16 alphabet
    # is uppercase according to RFC3548 section 6
    if not set(data) <= set("0123456789ABCDEF"):
        raise ValueError(
            """Base16 encoded data is invalid:
Data is not uppercase hex or it contains invalid characters."""
        )
    # For every two hexadecimal digits (= a byte), turn it into an integer.
    # Then, string the result together into bytes, and return it.
    return bytes(int(data[i] + data[i + 1], 16) for i in range(0, len(data), 2))


if __name__ == "__main__":
    import doctest

View on GitHub (pinned to f5988cc097)

Solutions

  1. Re-encode the source bytes with .hex().upper() (always even length) instead of hand-formatting.
  2. Pad a known-short value: data.zfill(len(data) + len(data) % 2).
  3. If odd length means corrupt data, reject it in your pipeline rather than repairing blindly.

Example fix

# before
base16_decode('f1a')  # ValueError: ...odd number of hex digits

# after
base16_decode('0f1a')  # b'\x0f\x1a'
Defensive patterns

Strategy: validation

Validate before calling

if len(data) % 2 != 0:
    raise ValueError(f'hex string must have even length, got {len(data)}')

Type guard

def is_even_length_hex(s: str) -> bool:
    return len(s) % 2 == 0 and set(s) <= set('0123456789ABCDEF')

Try / catch

try:
    base16_decode(data)
except ValueError as e:
    if 'even number' in str(e):
        base16_decode(data.zfill(len(data) + 1))
    else:
        raise

Prevention

When it happens

Trigger: Calling base16_decode('abc') (3 chars), base16_decode('0'), or any hex string of odd length. Even-length strings with bad characters hit the other ValueError instead.

Common situations: Hand-truncated hex strings, strings that lost a leading '0' (e.g. formatting with %X instead of %02X), or concatenating partial hex fragments.

Related errors


AI-assisted analysis of TheAlgorithms/Python@f5988cc097 (2026-08-14). Data as JSON: /api/errors/adcb2294cdfda0d3. Report an issue: GitHub.