prestodb/presto · error · ParquetDecodingException

Unable to read BINARY type decimal of size

Error message

Unable to read BINARY type decimal of size 

What it means

BinaryShortDecimalPlainValuesDecoder reads PLAIN-encoded BINARY values and converts each to a short decimal. Any value whose binary length exceeds 8 bytes cannot fit a short decimal unscaled value, so readNext throws a ParquetDecodingException with the offending size. This guards against silently truncating large decimals.

Source

Thrown at presto-parquet/src/main/java/com/facebook/presto/parquet/batchreader/decoders/plain/BinaryShortDecimalPlainValuesDecoder.java:51

    {
        requireNonNull(byteBuffer, "buffer is null");
        delegate = new BinaryPlainValuesDecoder(byteBuffer, bufferOffset, length);
    }

    @Override
    public void readNext(long[] values, int offset, int length)
    {
        ValueBuffer valueBuffer = delegate.readNext(length);
        int bufferSize = valueBuffer.getBufferSize();
        byte[] byteBuffer = new byte[bufferSize];
        int[] offsets = new int[length + 1];
        delegate.readIntoBuffer(byteBuffer, 0, offsets, 0, valueBuffer);

        for (int i = 0; i < length; i++) {
            int positionOffset = offsets[i];
            int positionLength = offsets[i + 1] - positionOffset;
            if (positionLength > 8) {
                throw new ParquetDecodingException("Unable to read BINARY type decimal of size " + positionLength + " as a short decimal");
            }

            values[offset + i] = getShortDecimalValue(byteBuffer, positionOffset, positionLength);
        }
    }

    @Override
    public void skip(int length)
    {
        checkArgument(length >= 0, "invalid length %s", length);
        delegate.skip(length);
    }

    @Override
    public long getRetainedSizeInBytes()
    {
        return INSTANCE_SIZE;
    }

View on GitHub (pinned to 55bb57d202)

Solutions

  1. Check the file's DECIMAL precision with parquet-tools and align the table schema/read type to it
  2. Cast or read as a long decimal (precision > 18) instead of a short decimal
  3. Rewrite the data with the correct short-decimal precision (<= 18) if values genuinely fit
  4. Fail fast at write time by validating unscaled values fit in 8 bytes before encoding

Example fix

// before: DECIMAL(30,5) file read as short decimal -> exception
// after: recreate table with matching precision
//   CREATE TABLE t (col DECIMAL(30,5)) ... or CAST to DECIMAL(30,5) on read
Defensive patterns

Strategy: validation

Validate before calling

// Before mapping the column to a short decimal, check its declared precision:
// if (precision > 18) use long decimal path
// parquet-tools schema file.parquet | grep 'DECIMAL'

Type guard

boolean fitsShortDecimal(int declaredPrecision) { return declaredPrecision <= 18; }

Try / catch

try {
    decoder.readNext(length);
} catch (ParquetDecodingException e) {
    if (e.getMessage().contains("as a short decimal")) {
        // switch to a long-decimal decoder for this column
    }
    throw e;
}

Prevention

When it happens

Trigger: readNext() over PLAIN-encoded binary decimal data where offsets[i+1]-offsets[i] > 8 for any value.

Common situations: DECIMAL columns written with precision > 18 (16-byte binary) but read/declared as short decimal; schema evolution where the table was altered to a smaller precision; external tables pointing at files with mismatched decimal annotations.

Related errors


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