prestodb/presto · error · ParsingException

Binary literal must contain an even number of digits

Error message

Binary literal must contain an even number of digits

What it means

A binary literal must encode whole bytes, so the hex string must have an even number of digits. BinaryLiteral checks hexString.length() % 2 and throws this ParsingException for odd-length values, since they cannot be decoded into complete bytes.

Source

Thrown at presto-parser/src/main/java/com/facebook/presto/sql/tree/BinaryLiteral.java:50

    private static final Pattern NOT_HEX_DIGIT_PATTERN = Pattern.compile(".*[^A-F0-9].*");

    private final Slice value;

    public BinaryLiteral(String value)
    {
        this(Optional.empty(), value);
    }

    public BinaryLiteral(Optional<NodeLocation> location, String value)
    {
        super(location);
        requireNonNull(value, "value is null");
        String hexString = WHITESPACE_PATTERN.matcher(value).replaceAll("").toUpperCase();
        if (NOT_HEX_DIGIT_PATTERN.matcher(hexString).matches()) {
            throw new ParsingException("Binary literal can only contain hexadecimal digits", location.get());
        }
        if (hexString.length() % 2 != 0) {
            throw new ParsingException("Binary literal must contain an even number of digits", location.get());
        }
        this.value = Slices.wrappedBuffer(BaseEncoding.base16().decode(hexString));
    }

    public BinaryLiteral(NodeLocation location, String value)
    {
        this(Optional.of(location), value);
    }

    /**
     * Return the valued as a hex-formatted string with upper-case characters
     */
    public String toHexString()
    {
        return BaseEncoding.base16().encode(value.getBytes());
    }

    public Slice getValue()

View on GitHub (pinned to 55bb57d202)

Solutions

  1. Pad the hex string with a leading zero to make the length even
  2. Fix the data source so full bytes are emitted
  3. Validate value.replaceAll("\\s","").length() % 2 == 0 before constructing

Example fix

// before
new BinaryLiteral(location, "ABC"); // 3 digits
// after
new BinaryLiteral(location, "0ABC"); // 4 digits, even
Defensive patterns

Strategy: validation

Validate before calling

String hex = value.replaceAll("\\s", "");
if (hex.length() % 2 != 0) {
    hex = "0" + hex; // left-pad to a whole byte
}

Type guard

boolean isEvenLengthHex(String value) {
    return value != null && value.replaceAll("\\s", "").length() % 2 == 0;
}

Try / catch

try {
    BinaryLiteral lit = new BinaryLiteral(location, value);
} catch (ParsingException e) {
    if (e.getMessage().contains("even number of digits")) {
        throw new MalformedBinaryLiteralException(value, e);
    }
    throw e;
}

Prevention

When it happens

Trigger: Constructing BinaryLiteral with an odd-length hex string, e.g. X'ABC' or X'123'.

Common situations: Hand-truncated hex dumps, off-by-one slicing of hex strings, padding dropped by string processing.

Related errors


AI-assisted analysis of prestodb/presto@55bb57d202 (2026-09-04). Data as JSON: /api/errors/745942dac67b1f9f. Report an issue: GitHub.